现在,我无法理解 API 中异步和同步代码执行之间的区别。 我希望看到 C# 中 async wait 用法的示例,这将清楚地向我展示为什么它很好。
我尝试创建一个简单的控制台应用程序项目,它将模拟 API 调用。
using System.Threading.Tasks;
namespace TestAppConsole
{
internal class Program
{
public static async Task Main()
{
var asyncProcessor = new AsyncDataProcessor();
await asyncProcessor.ProcessDataAsync();
}
}
}
using System;
using System.Threading.Tasks;
namespace TestAppConsole
{
public class AsyncDataProcessor
{
public async Task ProcessDataAsync()
{
var api1Data = await GetDataFromApi1Async();
var api2Data = await GetDataFromApi2Async();
var result = Process(api1Data, api2Data);
Console.WriteLine(result);
}
private async Task<string> GetDataFromApi1Async()
{
// Simulate an asynchronous API call
await Task.Delay(2000);
return "Data from API 1";
}
private async Task<string> GetDataFromApi2Async()
{
// Simulate another asynchronous API call
await Task.Delay(2000);
return "Data from API 2";
}
private string Process(string data1, string data2)
{
// Simulate data processing
return $"Processed: {data1} and {data2}";
}
}
}
我以为执行大约需要 2 秒,但实际上仍然需要 4 秒,就像同步代码一样。
请向我解释一下,如何在 WebAPI 中看到异步代码和同步代码之间的区别? 或者我在示例中做错了什么,所以它运行同步而不是异步?
问题是您在开始第一个呼叫之前等待第一个呼叫。第二次通话将在第一个通话结束后开始。您可以更改此设置:
public async Task ProcessDataAsync()
{
var api1task = GetDataFromApi1Async();
var api2task = GetDataFromApi2Async();
await Task.WhenAll(api1task, api2task);
var result = Process(api1task.Result, api2task.Result);
Console.WriteLine(result);
}
作为替代方案,您也可以写:
public async Task ProcessDataAsync()
{
var api1task = GetDataFromApi1Async();
var api2task = GetDataFromApi2Async();
var result = Process(await api1task, await api2task);
Console.WriteLine(result);
}
这将导致第一个任务启动,第二个任务立即启动。当这两个任务都启动时,将等待,这将带来预期的性能增益。
您当前正在等待
GetDataFromApi1Async
完成,然后再致电 GetDataFromApi2Async
。如果您要调用这两个方法,然后等待返回的任务,您会看到它们并行运行。例如:
public async Task ProcessDataAsync()
{
// Somewhat dangerous - see notes below
var api1Task = GetDataFromApi1Async();
var api2Task = GetDataFromApi2Async();
var api1Data = await api1Task;
var api2Data = await api2Task;
var result = Process(api1Data, api2Data);
Console.WriteLine(result);
}
现在,这确实有一个问题 - 如果
api1Task
和 api2Task
最终都出现故障,您将永远不会看到 api2Task
故障。有多种方法可以解决这个问题,但它们超出了您所要求的范围。