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

非同步代理程式庫(AAL)入門:基於角色的並行程式設計

     編輯:關於.NET

隨著多核心處理器普及,平行程式設計成為必備技能。Visual Studio 2010 引入非同步代理程式庫(Asynchronous Agents Library, AAL),提供基於角色(Actor)模型的高階平行架構:以訊息傳遞取代共享記憶體鎖,天然適合 I/O 密集、延遲敏感的應用。本文系統介紹 AAL 核心組件、訊息區塊管線、代理生命週期,並以電子郵件審查管線為例完整示範。

背景:為什麼需要角色模型?

  • 傳統平行技術(parallel_for、併發容器)著重計算並行,但無法解決 I/O 延遲。阿姆達爾定律指出:效能受限於最慢環節(常為 I/O 等待)。
  • 角色模型將元件視為獨立「角色」,透過非同步訊息通訊,各自維護狀態,無共享資料競爭,天然容忍延遲。
  • AAL 建構於Concurrency Runtime(CRT)之上:工作排程器 + 資源管理器,自動負載平衡至多核心。

一、訊息傳遞框架:管線化資料流

核心是訊息區塊,三種類型:

  • Source:僅傳播訊息(如 timer)。
  • Target:僅接收/處理/儲存訊息(如 call)。
  • Propagator:兼具 Source/Target(大多數區塊)。

內建訊息區塊一覽

區塊用途
unbounded_buffer<T>無限量儲存並傳播
overwrite_buffer<T>單一訊息,新訊息覆蓋舊訊息
single_assignment<T>單一寫入,後續寫入失敗
transformer<In,Out>接收 In,執行使用者函數轉為 Out,傳播
call<T>接收訊息,以負載為參數執行使用者函數(純 Target)
timer<T>定時產生訊息(純 Source)
choice<T1,T2...>多源競爭,取第一個就緒者
join<T>多源同步,等所有就緒合併為一訊息
multitype_join<T1,T2...>異型多源同步合併

管線組合範例:電子郵件審查 + 格式化

// 審查區塊:字典查找替換
var censor = new transformer<string, string>(s => {
    return dict.TryGetValue(s, out var r) ? r : s;
});

// 格式化區塊:大寫轉換
var format = new transformer<string, string>(s => s.ToUpper());

// 串連管線
censor.link_target(&format);

// 非同步發送、同步接收
asend(&censor, "foo");
var result = receive(format); // "FOO"

link_target 建立區塊連線,asend 非同步投遞,receive 阻塞等待結果。訊息在區塊間流動由 CRT 排程的輕量工作(LWT)自動處理,保證順序與無鎖並行。

訊息傳播協定內幕

  1. 來源呼叫 link_target 連線的目標 propagate 方法。
  2. 目標執行篩選器決定是否接受。
  3. 接受後放入輸入佇列,排程 LWT。
  4. LWT 執行處理步驟(如 transformer 執行使用者函數)並移至內部儲存。
  5. LWT 執行傳播步驟將訊息推送給下游目標。
  6. CRT 智慧合併 LWT:同一區塊同時間僅一個 LWT 活躍,新訊息直接由現有 LWT 處理,避免排程開銷。

二、非同步代理:粗粒度角色元件

agent 基類提供固定生命週期:

Created → start() → Runnable → (排程器挑選) → Started → run() 執行 → done() → Done
                    ↘ cancel() → Canceled
  • start():排程代理執行,進入 Runnable。
  • run():虛擬函數,實作代理主邏輯(阻塞式收發訊息、I/O、計算)。
  • done():標記完成,轉入 Done 終止狀態。
  • cancel():未啟動前取消;已啟動需自行處理取消邏輯。
  • 解構函數建議呼叫 agent::wait(this) 等待終止,避免殘留執行緒。

代理實作:ReaderAgent / WriterAgent

class ReaderAgent : public agent {
    ITarget<string>* _target;
    ReaderAgent(ITarget<string>* t) : _target(t) {}
    void run() override {
        while (!feof(stream)) 
            asend(_target, read_word(stream)); // 非同步送入管線
        asend(_target, "EOF"); // 結束訊號
        done();
    }
};

class WriterAgent : public agent {
    ISource<string>* _source;
    WriterAgent(ISource<string>* s) : _source(s) {}
    void run() override {
        while ((msg = receive(_source)) != "EOF")
            write_string(file, msg); // 阻塞等待管線輸出
        done();
    }
};

整合管線與代理

censor.link_target(&format);

ReaderAgent reader(&censor); reader.start();
WriterAgent writer(&format); writer.start();

// 主執行緒等待兩代理結束(透過解構函數 wait)

優勢:I/O 與計算完全重疊。Reader 非同步讀檔送入管線,Writer 同步接收寫檔,管線中間兩階段並行處理多筆資料,零鎖、零共享記憶體。

三、同步與進階主題

  • agent::wait()、wait_for_all()、wait_for_one() 等待代理終止。
  • 自訂訊息區塊:繼承 ITarget/ISource/IPropagator 介面。
  • 篩選器函數:建構區塊時傳入 lambda 決定是否接受特定訊息。
  • 例外處理:訊息攜帶例外資訊傳播,下游可捕獲。

總結

AAL 以訊息區塊管線實現細粒度資料流並行,以非同步代理封裝粗粒度 I/O 與控制流,配合 CRT 自動排程,讓開發者專注於資料流拓撲而非執行緒管理。適用於:管線化資料處理、異步 I/O 密集應用、事件驅動系統、需容忍延遲的分散式節點。建議從 MSDN 並行運算開發中心深入學習完整 API。

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