.NET 4.5+ 支援三種非同步模式:
MethodAsync + MethodCompleted 事件,舊版主流 (WebClient, BackgroundWorker)。Begin/End 配對,IAsyncResult,.NET 1.0 遺留。async/await + Task,現代標準 (C# 5.0+),WinRT/ASP.NET Core 唯一支援。新開發強烈建議使用 TAP。EAP 僅用於維護舊代碼或特定元件 (如 WebClient)。
MethodAsync(parameters):啟動非同步操作,立即返回。MethodAsync(parameters, userState):攜帶用戶狀態物件,支援多併發區分。MethodCompleted 事件:完成時觸發,EventArgs 包含 Result、Error、Cancelled、UserState。CancelAsync(userState):請求取消。IsBusy 屬性:是否有進行中操作。using System;
using System.Net;
namespace AsyncTest1.EAP
{
public class EAPRunTest1
{
public static void AsyncRun()
{
Utility.Log("AsyncRun:start");
string url = "https://sports.163.com/nba/";
using (WebClient webClient = new WebClient())
{
// 訂閱進度事件
webClient.DownloadProgressChanged += (s, e) =>
Utility.Log($"AsyncRun:download_progress|percent={e.ProgressPercentage}");
// 訂閱完成事件
webClient.DownloadStringCompleted += (s, e) =>
{
string log = "AsyncRun:download_completed";
log += $"|cancel={e.Cancelled}";
if (e.Error != null)
log += $"|error={e.Error.Message}";
else
log += $"|result_size={Utility.GetStrLen(e.Result)}";
Utility.Log(log);
};
webClient.DownloadStringAsync(new Uri(url));
Utility.Log("AsyncRun:download_start");
}
}
}
}
2012-12-28 00:39:39:621 AsyncRun:start
2012-12-28 00:39:40:377 AsyncRun:download_start
2012-12-28 00:39:40:903 AsyncRun:download_progress|percent=1
...
2012-12-28 00:39:41:582 AsyncRun:download_progress|percent=100
2012-12-28 00:39:41:614 AsyncRun:download_completed|cancel=False|result_size=205568
| 特性 | 說明 |
|---|---|
| 執行緒切換 | 完成事件在 ThreadPool 執行緒觸發,UI 應用需 Invoke 回主執行緒更新介面。 |
| userState 區分併發 | 同時發起多個請求時,透過 userState 識別屬於哪個請求。 |
| 錯誤處理 | 完成事件 Args.Error 為非 null 表示失敗,不拋出例外。 |
| 取消機制 | 呼叫 CancelAsync(userState),完成事件 Args.Cancelled = true。 |
public static Task DownloadStringTaskAsync(this WebClient client, Uri address)
{
var tcs = new TaskCompletionSource();
client.DownloadStringCompleted += (s, e) =>
{
if (e.Cancelled) tcs.SetCanceled();
else if (e.Error != null) tcs.SetException(e.Error);
else tcs.SetResult(e.Result);
};
client.DownloadStringAsync(address);
return tcs.Task;
}
// 使用
var html = await webClient.DownloadStringTaskAsync(new Uri(url));
EAP 透過「方法 + 完成事件」模式實現非同步,WebClient 是典型代表。理解 EAP 有助於維護舊系統、包裝舊 API 為 Task。新專案請直接使用 HttpClient + async/await (TAP),程式碼更線性、錯誤處理更自然、除錯體驗更佳。