首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

C# 委派與非同步呼叫實戰:以「做飯」為例輕鬆掌握非同步模式

     編輯:關於SqlServer

生活場景映射非同步模型

做飯過程天然包含非同步操作:

  • 燒水 → 下飯:有先後順序(同步序列)
  • 炒菜:與燒水/下飯獨立平行(非同步並行)
  • 現實中我們會「燒水的同時去炒菜」,水開再回來下飯——這就是非同步呼叫!

核心類別設計

Cooking 類(燒水+下飯,同步序列)

public class Cooking {
    public void StartCooking() {
        BoilingWater();  // 10 秒
        AddRice();       // 10 秒
    }
    private void BoilingWater() { /* Thread.Sleep(10000) */ }
    private void AddRice() { /* Thread.Sleep(10000) */ }
}

Frying 類(炒菜,獨立任務)

public class Frying {
    public void Fry() { /* Thread.Sleep(10000) */ }
}

Person 類(非同步協調者)

public delegate void AsyncDel();  // 無參無回傳委派

public class Person {
    private Cooking cooking = new Cooking();
    private Frying frying = new Frying();

    public void StartWork() {
        // 非同步啟動做飯
        AsyncDel ad1 = new AsyncDel(cooking.StartCooking);
        IAsyncResult ar1 = ad1.BeginInvoke(new AsyncCallback(CallbackMethod), ad1);

        // 非同步啟動炒菜
        AsyncDel ad2 = new AsyncDel(frying.Fry);
        IAsyncResult ar2 = ad2.BeginInvoke(null, null);

        // 等待兩者完成(阻塞當前執行緒)
        while (!ar1.IsCompleted) { /* 可做其他事 */ }
        while (!ar2.IsCompleted) { /* 可做其他事 */ }

        Console.WriteLine("開飯了.......");
    }

    // 回呼方法:結束非同步呼叫
    public void CallbackMethod(IAsyncResult ar) {
        AsyncDel ad = (AsyncDel)ar.AsyncState;
        ad.EndInvoke(ar);  // 必須呼叫 EndInvoke 釋放資源、取得回傳值/例外
    }
}

關鍵概念圖解

概念對應代碼說明
委派AsyncDel方法簽章的型別安全封裝
非同步啟動BeginInvoke立即返回 IAsyncResult,不阻塞
非同步狀態IAsyncResult.IsCompleted輪詢或等待完成
回呼AsyncCallback完成時自動執行,執行緒池執行緒上下文
結束非同步EndInvoke必須呼叫,否則資源洩漏、例外吞沒

移除 while 迴圈會發生什麼?

主執行緒直接跑到 Console.WriteLine("開飯了") 並結束程式,非同步任務還在背景執行緒跑,導致:

  • 程式過早退出,看不到「飯煮好」「炒菜好」輸出
  • 非同步操作被強制中斷

結論:非同步呼叫需明確等待完成(IsCompleted、AsyncWaitHandle、EndInvoke 阻塞等)。

現代替代方案(.NET 4.5+)

// Task-based Asynchronous Pattern (TAP) - 推薦
public async Task StartWorkAsync() {
    var cookTask = Task.Run(() => cooking.StartCooking());
    var fryTask = Task.Run(() => frying.Fry());
    await Task.WhenAll(cookTask, fryTask);
    Console.WriteLine("開飯了.......");
}

async/await + Task 取代委派非同步模式(APM),更簡潔、例外處理更自然、支援取消權杖、進度回報。

總結

委派非同步(BeginInvoke/EndInvoke)是理解非同步本質的基石。掌握「啟動→等待/回呼→結束」三階段,再升級到 Task/async/await,才能寫出高效、健壯的並行程式。

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