异步编程在C#中有多种实现方式,其中两个主要的模型是基于任务的异步(Task-based Asynchronous Programming,TAP)和基于事件的异步(Event-based Asynchronous Pattern,EAP)。此外,还有一些其他的方式,例如异步委托和异步流。以下是这些主要实现方式的简要介绍:
任务(Task)和async
/await
: 这是C#中最常见的异步编程模型。使用async
和await
关键字,可以轻松地编写异步代码,而不用显式地管理线程或回调。Task
类表示一个异步操作,async
关键字用于定义异步方法。
async Task<string> GetDataAsync()
{
// 异步操作
await Task.Delay(1000);
return "Data loaded!";
}
异步事件模型(Event-based Asynchronous Pattern,EAP): 这是.NET Framework中早期的异步编程模型。它基于事件和回调函数,通常使用BeginXXX
和EndXXX
方法表示异步操作的开始和结束。
void GetDataAsync()
{
var client = new WebClient();
client.DownloadStringCompleted += (sender, e) =>
{
string result = e.Result;
// 处理结果
};
client.DownloadStringAsync(new Uri("https://example.com"));
}
异步委托(Asynchronous Delegate): 这是.NET Framework早期支持的一种异步编程方式,使用BeginInvoke
和EndInvoke
方法。虽然不如TAP那么直观,但在一些旧的代码中仍可能遇到。
delegate string MyDelegate(string input);
IAsyncResult result = myDelegate.BeginInvoke("input", ar =>
{
string output = myDelegate.EndInvoke(ar);
// 处理结果
}, null);
异步流(Asynchronous Streams): 异步流是在C# 8.0及以上版本引入的,通过await foreach
语法支持异步枚举。这使得异步返回多个值的场景更加方便。
async IAsyncEnumerable<int> GenerateNumbersAsync()
{
for (int i = 0; i < 5; i++)
{
await Task.Delay(100);
yield return i;
}
}
async Task ProcessAsync()
{
await foreach (var number in GenerateNumbersAsync())
{
// 处理每个数字
}
}
这些实现方式提供了不同的抽象层次和语法,可以根据特定的需求和代码场景来选择。大多数新的异步代码使用async
和await
,而EAP和异步委托主要是在早期版本的.NET Framework中使用。异步流则适用于需要异步产生多个值的情况。