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-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
这样,当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
这样,当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);
}
}
这将以以下方式进行:
.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);
}
}
这将以以下方式进行:
.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饱和等问题。。。你能说得更具体些吗