隨著多核心處理器普及,平行程式設計成為必備技能。Visual Studio 2010 引入非同步代理程式庫(Asynchronous Agents Library, AAL),提供基於角色(Actor)模型的高階平行架構:以訊息傳遞取代共享記憶體鎖,天然適合 I/O 密集、延遲敏感的應用。本文系統介紹 AAL 核心組件、訊息區塊管線、代理生命週期,並以電子郵件審查管線為例完整示範。
parallel_for、併發容器)著重計算並行,但無法解決 I/O 延遲。阿姆達爾定律指出:效能受限於最慢環節(常為 I/O 等待)。核心是訊息區塊,三種類型:
timer)。call)。| 區塊 | 用途 |
|---|---|
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)自動處理,保證順序與無鎖並行。
link_target 連線的目標 propagate 方法。agent 基類提供固定生命週期:
Created → start() → Runnable → (排程器挑選) → Started → run() 執行 → done() → Done
↘ cancel() → Canceled
start():排程代理執行,進入 Runnable。run():虛擬函數,實作代理主邏輯(阻塞式收發訊息、I/O、計算)。done():標記完成,轉入 Done 終止狀態。cancel():未啟動前取消;已啟動需自行處理取消邏輯。agent::wait(this) 等待終止,避免殘留執行緒。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 介面。AAL 以訊息區塊管線實現細粒度資料流並行,以非同步代理封裝粗粒度 I/O 與控制流,配合 CRT 自動排程,讓開發者專注於資料流拓撲而非執行緒管理。適用於:管線化資料處理、異步 I/O 密集應用、事件驅動系統、需容忍延遲的分散式節點。建議從 MSDN 並行運算開發中心深入學習完整 API。