概述C#代碼協同執行
C#代碼協同執行的支持機制
幾個月前我曾大致分析過 C# 2.0 中 iterator block 機制的實現原理,《C# 2.0 中Iterators的改進與實現原理淺析》,文中簡要介紹了 C# 2.0 是如何在不修改 CLR 的前提下由編譯器,通過有限狀態機來實現 iterator block 中 yield 關鍵字。實際上,這一機制的最終目的是提供一個C#代碼協同執行的支持機制。
- using System.Collections.Generic;
- public class Tokens : IEnumerable<string>
- {
- public IEnumerator<string> GetEnumerator()
- {
- for(int i = 0; i<elements.Length; i++)
- yield elements[i];
- }
- }
- foreach (string item in new Tokens())
- {
- Console.WriteLine(item);
- }
在這段代碼執行過程中,foreach 的循環體和 GetEnumerator 函數體實際上是在同一個線程中交替執行的。這是一種介于線程和順序執行之間的協同執行模式,之所以稱之為協同(Coroutine),是因為同時執行的多個代碼塊之間的調度是由邏輯隱式協同完成的。順序執行無所謂并行性,而線程往往是由系統調度程序強制性搶先切換,相對來說Win3.x 中的獨占式多任務倒是與協同模型比較類似。
就協同執行而言,從功能上可以分為行為、控制兩部分,控制又可進一步細分為控制邏輯和控制狀態。行為對應著如何處理目標對象,如上述代碼中:行為就是將目標對象打印到控制臺;控制則是如何遍歷這個 elements 數組,可進一步細分為控制邏輯(順序遍歷)和控制狀態(當前遍歷到哪個元素)。下面將按照這個邏輯介紹不同語言中如何實現和模擬這些邏輯。
以 Ruby 語言(語法類似 Python)介紹了 Iterator 機制是如何簡化遍歷操作的代碼。實際上中心思想就是將行為與控制分離,由語言層面的支持來降低控制代碼的薄記工作。
- deftextfiles(dir)
- Dir.chdir(dir)
- Dir["*"].eachdo|entry|
- yielddir+"\"+entryif/^.*.txt$/=~entry
- ifFileTest.directory?(entry)
- textfiles(entry){|file|yielddir+"\"+file}
- end
- end
- Dir.chdir("..")
- end
- textfiles(“c:\”){|file|
- putsfile
- }
例如上面這段 Ruby 的遞歸目錄處理代碼中,就采用了與 C# 2.0 中完全類似的語法實現協同執行支持。
對 C# 1.0 和 C++ 這類不支持協同執行的語言,協同執行過程中的狀態遷移或者說執行緒的調度工作,需要由庫和使用者自行實現,例如 STL 中的迭代器 (iterator) 自身必須保存了與遍歷容器相關的位置信息。例如在 STL 中實現協同執行:
- #include<vector>
- #include<algorithm>
- #include<iostream>
- //ThefunctionobjectmultipliesanelementbyaFactor
- template<classType>
- classMultValue
- {
- private:
- TypeFactor;//Thevaluetomultiplyby
- public:
- //Constructorinitializesthevaluetomultiplyby
- MultValue(constType&_Val):Factor(_Val){
- }
- //Thefunctioncallfortheelementtobemultiplied
- voidoperator()(Type&elem)const
- {
- elem*=Factor;
- }
- };
- intmain()
- {
- usingnamespacestd;
- vector<int>v1;
- //
- //Usingfor_eachtomultiplyeachelementbyaFactor
- for_each(v1.begin(),v1.end(),MultValue<int>(-2));
- }
雖然 STL 較為成功的通過迭代器、算法和謂詞,將此協同執行邏輯中的行為和控制分離,謂詞表現行為(MultValue<int>、迭代器(v1.being(), v1.end())表現控制狀態、算法表現控制邏輯(for_each),但仍然存在編寫復雜,使用麻煩,并且語義不連冠的問題。以上介紹C#代碼協同執行的支持機制。
【編輯推薦】