MSDN說:
需要使用者互動的軟體必須儘快回應使用者的活動,以便提供豐富的使用者經驗。不過,同時它也必須執行需要的計算以儘快提供使用者資料。在個人目前的工作領域,使用者體驗並非放在第一(甚至是最後一名),大部分時間都花在Coding工作處理常式(Routines),主要實現概念為狀態機(State-Machine)與多工處理(Multi-Task),在Main Thread執行
常式內的多工工作是純粹的商業邏輯,少有牽涉I/O存取,處理頻率穩定近乎週期性,但來源資訊難免要透過外部裝置取得,如網路介面、PCI裝置、使用者輸入...等,幾乎是慢速、頻率較低的資料源,為了避免影響Main Thread的多工輪詢,此時就可考慮用其他Thread分擔低速工作。
整理三個與狀態機搭配的常用分緒招,共通點是在Main Thread輪詢某資料狀態,該輪詢函式必須不能阻塞(Blocking)住Main Thread,否則會影響到其他多工作業
(沒實測過這些方法的具體效能,比較在乎應用上的設計模式(Pattern)是否容易嵌入既有架構)
- Task
- 發動:
- 將要執行的Method裝載到Task物件中後,呼喚Start()開始執行緒作業
- 也可以利用工廠模式,呼叫共用方法Task.Run()開始執行緒作業,同步狀態透過傳回的Task實例來操作
- 同步:
- Worker Thread輪詢Task.IsComplete至狀態為True
- 心得:
- Task封裝了Thread與若干執行緒同步元件(如Mutex),因此包含了執行緒操作與同步操作
- 據說是在執行緒池內作業(待確認
- ThreadPool
- 發動:
- 將要執行的Method透過QueueUserWorkItem傳入執行緒池
- 同步:
- 無法得知方法最終被放到哪個具體執行緒,也沒封裝同步操作方法,所以必須在Method裡自行設計同步物件來辨識是否方法執行完成
- 個人慣用Concurrent執行緒安全元件,如ConcurrentQueue、ConcurrentDictionary傳遞資訊到Worker Thread
- Worker Thread輪詢Concurrent元件
- 心得:
- 最簡單易用赤裸的異步編成模式,不含任何同步方法的純粹執行緒池操作最?似乎懂了些什麼了?
- MulticastDelegate
- 發動:
- 將要執行的Method裝載到Delegate中
- 呼叫該Delegate的BeginInvoke(),必須帶入回呼方法(Callback)
- 必須呼叫EndInvoke()作為確認該執行緒執行完成的辨識?
- 同步:
- 輪詢呼叫該Delegate時傳回的IAsyncResult.IsCompleted
- 或是在Main Thread呼叫EndInvoke()(但是可能阻塞)
- 心得:
- 與Task一樣,封裝了執行緒操作與同步操作,只是設計模式上透過IAsyncResult或EndInvoke達成同步
- 據說是在執行緒池內作業(待確認
class Program { static void Main(string[] args) { int state = 0; Action __delegate = null; Task __task = null; IAsyncResult handle = null; ConcurrentQueueexchange = new ConcurrentQueue (); int outValue = 0; //the main state machine Program.method(); while (state != 500) { switch (state) { case 0: // use Task __task = new Task(new Action(Program.method)); __task.Start(); state +=10; break; case 10: // wait until task done if (__task.IsCompleted) state +=10; break; case 20: // use thread pool ThreadPool.QueueUserWorkItem((object foo)=>{ Program.method(); exchange.Enqueue(0); // enqueue some meaningfll result },null); state+=10; break; case 30: //wait until method had been scheduled and executed if (exchange.TryDequeue(out outValue)) state +=10; break; case 40: // use delegate/IAsyncResult __delegate = new Action(method); handle = __delegate.BeginInvoke((IAsyncResult ar)=> { method(); __delegate.EndInvoke(ar); // you had to call this to release ar },null); break; case 50: // wait until method had been executed if (handle.IsCompleted) state = 500; break; default: break; } Thread.Sleep(0);// yield to other thread to run }//while } static void method() { //reflect the current thread Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId.ToString()); } }
後記1:MSDN的異步編程模式概述,對於非同步作業可有概略且完整的認識,其中APM(
Asynchronous Programming Model,就是Delegate/IAyncResult)已經漸漸式微變成不太推薦的Pattern
沒有留言:
張貼留言