首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 異步編程入門:Delegate BeginInvoke/EndInvoke 模式全解析

     編輯:關於C#

委托異步調用基礎

.NET 早期異步模式(APM)通過委托的 BeginInvoke/EndInvoke 實現異步執行。BeginInvoke 立即返回 IAsyncResult,EndInvoke 獲取返回值或傳播異常。

四種獲取結果的方式

1. 直接調用 EndInvoke(阻塞等待)


delegate int NewTaskDelegate(int ms);
static int NewTask(int ms)
{
    Console.WriteLine("任務開始");
    Thread.Sleep(ms);
    return new Random().Next(10000);
}
static void Main()
{
    NewTaskDelegate task = NewTask;
    IAsyncResult ar = task.BeginInvoke(2000, null, null);
    int result = task.EndInvoke(ar); // 阻塞 2 秒
    Console.WriteLine(result);
}

若不調用 EndInvoke,後台線程任務未完成進程就會退出。

2. 輪詢 IAsyncResult.IsCompleted


IAsyncResult ar = task.BeginInvoke(2000, null, null);
while (!ar.IsCompleted)
{
    Console.Write("*");
    Thread.Sleep(100);
}
int result = task.EndInvoke(ar);

可在等待期間顯示進度,改善用戶體驗。

3. 使用 AsyncWaitHandle.WaitOne


IAsyncResult ar = task.BeginInvoke(2000, null, null);
while (!ar.AsyncWaitHandle.WaitOne(100, false))
{
    Console.Write("*");
}
int result = task.EndInvoke(ar);

WaitOne(100) 等待 100ms,超時返回 false,避免忙等待。

4. 回調模式(真正的非阻塞)


delegate int MyMethod();
private int Method()
{
    Thread.Sleep(10000);
    return 100;
}
private void Callback(IAsyncResult ar)
{
    if (ar == null) return;
    var del = (MyMethod)ar.AsyncState;
    textBox1.Text = del.EndInvoke(ar).ToString();
}
private void Button_Click(object sender, EventArgs e)
{
    MyMethod my = Method;
    my.BeginInvoke(Callback, my); // 立即返回,UI 不凍結
}

回調方法在線程池線程中執行,訪問 UI 控件需注意跨線程調用(後續講解)。

其他組件的 Begin/End 模式

如 HttpWebRequest.BeginGetResponse/EndGetResponse:


private void RequestCallback(IAsyncResult ar)
{
    var req = (HttpWebRequest)ar.AsyncState;
    var resp = (HttpWebResponse)req.EndGetResponse(ar);
    var sr = new StreamReader(resp.GetResponseStream());
    textBox1.Text = sr.ReadToEnd();
}
private void Button_Click(object sender, EventArgs e)
{
    var req = (HttpWebRequest)WebRequest.Create("https://example.com");
    req.BeginGetResponse(RequestCallback, req);
}

總結

APM 模式雖已被 Task/async-await 取代,但理解其原理有助於掌握異步編程本質。關鍵點:

  • BeginInvoke 創建後台線程
  • EndInvoke 必須調用以獲取結果/異常
  • 回調模式實現真正非阻塞
  • 所有 BeginXxx 線程均為後台線程

任務管理器線程數 輪詢輸出效果

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved