.NET 提供了执行异步操作的三种模式:
-
基于任务的异步模式 (Task-based Asynchronous Pattern, TAP)
-
该模式使用单一方法表示异步操作的开始和完成。 TAP 是在 .NET Framework 4 中引入的。 这是在 .NET 中进行异步编程的推荐方法。 C# 中的 async 和 await 关键词为 TAP 添加了语言支持。
-
样例 // 定义一个异步执行的方法 private async void OnTaskAsync(object sender, System.EventArgs e) { // 用于任务的取消 System.Threading.CancellationTokenSource cts = new System.Threading.CancellationTokenSource(); var clientHandler = new System.Net.Http.HttpClientHandler(); var client = new System.Net.Http.HttpClient(clientHandler); ... var response = await client.GetAsync(req.Url, _cts.Token); response.EnsureSuccessStatusCode(); string resp = await response.Content.ReadAsStringAsync(); await System.Threading.Tasks.Task.Run(() => { var images = req.Parse(resp); foreach (var image in images) { cts.Token.ThrowIfCancellationRequested(); ... } }, cts.Token); }
-
-
基于事件的异步模式 (Event-based Asynchronous Pattern, EAP)
-
是提供异步行为的基于事件的旧模型。 这种模式需要后缀为
Async
的方法,以及一个或多个事件、事件处理程序委托类型和EventArg
派生类型。 EAP 是在 .NET Framework 2.0 中引入的。 建议新开发中不再使用这种模式。 -
样例 var client = new System.Net.WebClient(); client.DownloadStringCompleted += OnDownloadStringCompleted; client.DownloadStringAsync(new System.Uri(...)); private void OnStringCompletedEventHandler(object sender, System.Net.DownloadStringCompletedEventArgs e) { ... }
-
-
异步编程模型模式 (Asynchronous Programming Model, APM)
-
这是使用 IAsyncResult 接口提供异步行为的旧模型。 在这种模式下,同步操作需要
Begin
和End
方法(例如,BeginWrite
和EndWrite
以实现异步写入操作)。 不建议新的开发使用此模式。 -
样例 System.Action<> downloadString = () => { var client = new System.Net.WebClient(); ... return client.DownloadString(address); }; System.IAsyncResult ar = downloadString.BeginInvoke(null, null); ... downloadString.EndInvoke(ar);
-
模式的比较
为了快速比较这三种模式的异步操作方式,请考虑使用从指定偏移量处起将指定量数据读取到提供的缓冲区中的Read
方法:
public class MyClass { public int Read(byte [] buffer, int offset, int count); }
此方法对应的 TAP 将公开以下单个 ReadAsync
方法:
public class MyClass { public Task<int> ReadAsync(byte [] buffer, int offset, int count); }
对应的 EAP 将公开以下类型和成员的集:
public class MyClass
{
public void ReadAsync(byte [] buffer, int offset, int count);
public event ReadCompletedEventHandler ReadCompleted;
}
对应的 APM 将公开 BeginRead
和 EndRead
方法:
public class MyClass
{
public IAsyncResult BeginRead(byte [] buffer, int offset, int count, AsyncCallback callback, object state);
public int EndRead(IAsyncResult asyncResult);
}