Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 用.NET内核进行异步编程?_C#_Async Await_Asp.net Core_Task Parallel Library_.net Core - Fatal编程技术网

C# 用.NET内核进行异步编程?

C# 用.NET内核进行异步编程?,c#,async-await,asp.net-core,task-parallel-library,.net-core,C#,Async Await,Asp.net Core,Task Parallel Library,.net Core,我是.netcore和异步编程的新手。我正在尝试实现一个控制台应用程序,以执行以下操作: 控制台应用程序应该作为两个外部API之间的中介。例如API-1和API-2 它应该在每10毫秒后调用API-1以获取数据 立即调用API-2以提交从API-1收到的数据 控制台应用程序需要等待API-1接收数据,但不必等待API-2的响应 下面是我的代码。它没有按预期工作。起初,它会像预期的那样在10毫秒内调用API-1,但此后,它只有在收到API-2的响应后才会调用API-1。 假设API-2需要20秒,

我是
.netcore
和异步编程的新手。我正在尝试实现一个控制台应用程序,以执行以下操作:

  • 控制台应用程序应该作为两个外部API之间的中介。例如API-1和API-2

  • 它应该在每10毫秒后调用API-1以获取数据

  • 立即调用API-2以提交从API-1收到的数据

  • 控制台应用程序需要等待API-1接收数据,但不必等待API-2的响应
  • 下面是我的代码。它没有按预期工作。起初,它会像预期的那样在10毫秒内调用API-1,但此后,它只有在收到API-2的响应后才会调用API-1。
    假设API-2需要20秒,API-1也会在20秒后被调用

    如何使API-2调用异步,使其不必等待API-2响应

    namespace ConsoleApp1
    {
        public class Program
        {
            private static Timer _timer;
            private const int TIME_INTERVAL_IN_MILLISECONDS = 10; // 10 milliseconds
            private const int API2_DELAY = 20000; // 20 seconds
            public static void Main(string[] args)
            {
                Dowork().Wait();
                Console.WriteLine("Press Any Key to stop");
                Console.ReadKey();
                Console.WriteLine("Done");
            }
    
            private static async Task Dowork()
            {
                var data = new SomeData();
                _timer = new Timer(CallAPI1, data, TIME_INTERVAL_IN_MILLISECONDS, Timeout.Infinite);
                await Task.Yield();            
            }
    
            private static async void CallAPI1(object state)
            {           
                var data = state as SomeData;
    
                Console.WriteLine("Calling API One to get some data.");
                data.SomeStringValue = DateTime.Now.ToString();
    
                await CallAPI2(data);
                _timer.Change(TIME_INTERVAL_IN_MILLISECONDS, Timeout.Infinite);
            }
    
            private static async Task CallAPI2(SomeData data)
            {           
                Console.WriteLine("Calling API Two by passing some data received from API One " + data.SomeStringValue);
    
                // the delay represent long running call to API 2
                await Task.Delay(API2_DELAY);
            }
        }
    }
    
    POCO类

    namespace ConsoleApp1
    {
        public class SomeData
        {
            public string SomeStringValue { get; set; }
        }
    }
    
    还要注意,API-1和API-2将在ASP.NET Core 1中开发

    更新1
    让我重述一下上面的句子。API-1将在.Net核心中开发,但API-2将是windows工作流服务。这意味着我们可以多次调用WF。WF将持久化请求,并一次处理一个请求

    更新2

    在浏览了所有提供的答案和链接之后。我正在考虑使用windows服务作为中间程序,而不是控制台应用程序。目前,
    .Net core
    不支持windows服务,但它可以在windows服务中承载.Net core,或者我可以使用4.6.2版本的经典windows服务。我想我也可以在windows服务中实现异步

    调用API2时删除等待

        private static async void CallAPI1(object state)
        {
            var data = state as SomeData;
    
            Console.WriteLine("Calling API One to get some data.");
            data.SomeStringValue = DateTime.Now.ToString();
            //Before this will cause the program to wait
            await CallAPI2(data);
            // Now it will call and forget
            CallAPI2(data);
            _timer.Change(TIME_INTERVAL_IN_MILLISECONDS, Timeout.Infinite);
        }
    
    编辑:

    正如大卫所指出的,当然有很多方法可以解决这个问题。这不是解决问题的正确方法

    另一种方法是使用quartz.net

  • 将API1计划为重复作业
  • 完成API1后,安排另一个作业作为独立作业运行API2

  • 这样,当API2失败时,您可以重播/重复作业。

    在调用API2时删除等待

        private static async void CallAPI1(object state)
        {
            var data = state as SomeData;
    
            Console.WriteLine("Calling API One to get some data.");
            data.SomeStringValue = DateTime.Now.ToString();
            //Before this will cause the program to wait
            await CallAPI2(data);
            // Now it will call and forget
            CallAPI2(data);
            _timer.Change(TIME_INTERVAL_IN_MILLISECONDS, Timeout.Infinite);
        }
    
    编辑:

    正如大卫所指出的,当然有很多方法可以解决这个问题。这不是解决问题的正确方法

    另一种方法是使用quartz.net

  • 将API1计划为重复作业
  • 完成API1后,安排另一个作业作为独立作业运行API2

  • 这样,当API2失败时,您可以重播/重复作业。

    在这种情况下,我会做很多不同的事情。我会使用
    Task.Delay
    ,而不是使用计时器——我当然会等待API2完成,然后再尝试向其抛出更多数据。此外,我要确保我的
    async
    方法是
    Task
    Task
    返回,注意您的
    CallAPI1
    调用不是,我知道这是一个计时器回调——但这是另一个问题

    考虑以下几点:

    async Task IntermediateAsync()
    {
        Console.WriteLine("Press ESC to exit...");
    
        while (Console.ReadKey(true).Key != ConsoleKey.Escape)
        {
            var result = await _apiServiceOne.GetAsync();
            await _apiServiceTwo.PostAsync(result);
    
            // Wait ten milliseconds after each successful mediation phase
            await Task.Delay(10);
        }
    }
    
    这将以以下方式进行:

  • 打印一行,指示用户如何退出
  • 起动回路
  • 得到API1的结果
  • 将结果传递给API2
  • 等待10毫秒
  • [步骤2]
  • 最后,无论您是否使用
    .netcore
    ,这都是相同的建议。任何API交互都应该遵循相同的准则

    注释


    在第二个API调用中使用fire-and-forget只是将代码设置为失败。由于它是一个API调用,
    I/O
    绑定操作很可能会有一些延迟,我们应该假设10毫秒的紧密循环只会淹没该端点上的可用性。为什么不干脆等它结束,你有什么理由呢?

    在这种情况下,我会做很多不同的事情。我会使用
    Task.Delay
    ,而不是使用计时器——我当然会等待API2完成,然后再尝试向其抛出更多数据。此外,我要确保我的
    async
    方法是
    Task
    Task
    返回,注意您的
    CallAPI1
    调用不是,我知道这是一个计时器回调——但这是另一个问题

    考虑以下几点:

    async Task IntermediateAsync()
    {
        Console.WriteLine("Press ESC to exit...");
    
        while (Console.ReadKey(true).Key != ConsoleKey.Escape)
        {
            var result = await _apiServiceOne.GetAsync();
            await _apiServiceTwo.PostAsync(result);
    
            // Wait ten milliseconds after each successful mediation phase
            await Task.Delay(10);
        }
    }
    
    这将以以下方式进行:

  • 打印一行,指示用户如何退出
  • 起动回路
  • 得到API1的结果
  • 将结果传递给API2
  • 等待10毫秒
  • [步骤2]
  • 最后,无论您是否使用
    .netcore
    ,这都是相同的建议。任何API交互都应该遵循相同的准则

    注释


    在第二个API调用中使用fire-and-forget只是将代码设置为失败。由于它是一个API调用,
    I/O
    绑定操作很可能会有一些延迟,我们应该假设10毫秒的紧密循环只会淹没该端点上的可用性。为什么不简单地等待它完成,你可能有什么原因?

    可能重复@LP13为什么API2慢?它在干什么?对速度较慢的服务进行多次调用可能会使其饱和。您可能会遇到线程饥饿、I/O饱和等问题。。。所以,您可以更具体地避免API-2是windows工作流服务在执行一些长时间运行的任务。对于控制台应用程序,它应该是fire and forget调用。@JeroenHeier为什么我需要避免异步无效?可能与@LP13重复为什么API2很慢?它在干什么?对速度较慢的服务进行多次调用可能会使其饱和。您可能会遇到线程饥饿、I/O饱和等问题。。。你能说得更具体些吗