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

.NET 非同步機制入門:委派與 BeginInvoke/EndInvoke 基礎實戰(入門篇)

     編輯:關於.NET

同步與非同步的執行緒差異

先看一個經典的同步 Hello World:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("1,Thread ID:#{0}, IsPoolThread?{1}",
            Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
        AsyncTest test = new AsyncTest();
        string val = test.Hello("Andy Huang");
        Console.WriteLine(val);
        Console.ReadLine();
    }
}
public class AsyncTest
{
    public string Hello(string name)
    {
        Console.WriteLine("2,Thread ID:#{0}, IsPoolThread?{1}",
            Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
        return "Hello:" + name;
    }
}

輸出顯示主程式與 Hello 方法在**同一個非執行緒池執行緒**上執行(IsPoolThread=False),這就是典型的同步阻塞呼叫。

第一個非同步 Hello World

透過委派的 BeginInvoke / EndInvoke 即可將工作排入執行緒池:

// 1. 宣告委派
public delegate string AsyncEventHandler(string name);

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("1,Thread ID:#{0}, IsPoolThread?{1}",
            Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
        AsyncTest test = new AsyncTest();
        AsyncEventHandler async = test.Hello; // 指派目標方法
        IAsyncResult result = async.BeginInvoke("Andy Huang", null, null); // 非同步啟動
        string val = async.EndInvoke(result); // 等待並取得結果
        Console.WriteLine(val);
        Console.ReadLine();
    }
}
public class AsyncTest
{
    public string Hello(string name)
    {
        Console.WriteLine("2,Thread ID:#{0}, IsPoolThread?{1}",
            Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
        return "Hello:" + name;
    }
}

輸出關鍵差異:2,Thread ID:#10, IsPoolThread?True —— 方法現在在**執行緒池執行緒**上跑,主執行緒在 EndInvoke 處阻塞等待結果。

委派背後的秘密:編譯器產生的 sealed 類別

使用 IL Disassembler (ildasm) 或 Reflector 反編譯,發現委派實際上是一個繼承 MulticastDelegate 的 sealed class:

public sealed class AsyncEventHandler : MulticastDelegate
{
    public AsyncEventHandler(object @object, IntPtr method) { }
    public virtual IAsyncResult BeginInvoke(string name, AsyncCallback callback, object @object) { }
    public virtual string EndInvoke(IAsyncResult result) { }
    public virtual string Invoke(string name) { }
}
  • Invoke:同步呼叫入口,參數/回傳與原方法一致。
  • BeginInvoke / EndInvoke:非同步成對方法,BeginInvoke 多出 AsyncCallback 與 object state,回傳 IAsyncResult;EndInvoke 接收 IAsyncResult 並回傳結果。

何時使用 .NET 非同步機制?

適用於**執行時間較長**的作業,避免阻塞主執行緒(UI 凍結、請求排隊):

  • 檔案/流/網路 I/O(FileStream, Socket, HttpWebRequest)
  • 資料庫查詢與交易
  • Web Service / WCF 呼叫
  • 大量運算、影像處理
  • 訊息佇列 (MessageQueue)

.NET Framework 在 System.IO、System.Net、System.Data、System.Messaging、ASP.NET 等命名空間廣泛內建非同步版本(BeginXxx/EndXxx 或 Task-based),開發者可直接使用。

小結

本文建立了最基礎的認知:

  1. 委派是 .NET 非同步的核心載體,編譯器自動產生 BeginInvoke/EndInvoke。
  2. 非同步呼叫會切換到**執行緒池執行緒**執行,主執行緒可繼續或等待。
  3. EndInvoke 必須呼叫,否則資源洩漏。

下一篇將深入探討 IAsyncResult 狀態機制、回呼模式、AsyncState 傳遞與異常處理細節。

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