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
- 發動:
- 同步:
- 心得:
- 最簡單易用赤裸的異步編成模式,不含任何同步方法的純粹執行緒池操作最?似乎懂了些什麼了?
- 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;
ConcurrentQueue exchange = 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
後記2:在.NET Core(MAC)上實測Delegate.BeginInvoke是會有例外的,原因
在此,大致上是被開發小組視為Deprecated方法,未來可能會被幹掉