CCR,並發與協調運行時(Concurrency and Coordination Runtime)。從名字裡我們就可以知道,這個東東是用來簡化並發程式設計的。為何要並發呢?因為我們有多個任務需要處理,如果能同時做就會充分利用硬體而減少處理的時間。自然的,CCR也是以“任務”為核心進行設計的,CCR中的代碼也可以分為如下幾個功能:描述任務、產生任務、調度任務和執行任務。
描述任務
對於電腦來說一個任務就是一段需要執行的代碼,於是CCR有一個對任務的最抽象描述:ITask介面
任務被封裝在ITask執行個體中,當CCR調度這個任務執行個體去執行之後,CCR會調用ITask.Execute方法來執行該任務。在ITask介面之下,派生出來各種各樣的Task
本節討論的是CCR的整體結構,後面我們會具體討論這些classes。
產生任務
對於電腦來說,任務都是類似的:按給定的參數執行一個給定的方法。但是對於程式員來說,往往並非這麼簡單。從時序上來講,任務可以分為這麼幾種情況:演算法和參數都已經齊備的、已知演算法等待參數的和已知參數等待演算法的。對於第一種情況,直接使用Thread或者ThreadPool也可以很方便的解決問題,當然CCR也提供了相應的支援。對於後面兩種情況,CCR使用了計算過程與參數分離描述的方法來解決。電腦的程式的作用就是處理流程相對固定的事務,往往計算邏輯是有限的而參數是變化無窮的。於是CCR將計算過程與參數分離開來,調用者不需要知道如何處理這些參數,甚至不需要知道是誰何時來進行處理,它只需要把要計算的資料發送到一個特定的地方即可,而這些資料會被可信賴的得以處理。當計算過程接收到適當的參數的時候,也就產生了任務。CCR中Port和PortSet類型就是這樣的參數儲存空間。ReceiverTask及其子類則是封裝計算過程的類型,Port可以被註冊到相應的ReceiverTask中,當有其他使用者向Port中投遞元素時,就會產生任務並放入相應的DispatcherQueue中等待調度。
調度任務
需要執行的任務是有先來後到、輕重緩急的,同時電腦的CPU資源是有限度,每個核(包括超執行緒的邏輯核)在同一時間只能處理一個線程。這時候就需要進行一定的調度。為了充分利用CPU,自然是要使用多線程來執行任務。如果不使用CCR,我們也可以用.net內建的Thread和ThreadPool都可以用的並行任務調度,其中又數ThreadPool用起來比較簡單,直接把要執行的方法丟進去就好了。但是這簡單的背後也存在問題,雖然是解決了任務的先來後到,但是沒辦法分輕重緩急了,ThreadPool堅持認定CPU面前人人平等的原則,晚來的就是要侯著等先到底執行完。直接用Thread也有問題,就是無法很容易的控制線程的數量以及重用線程,而線程本身又是一個比較重型的資源,反反覆複的建立和銷毀很影響效率。為瞭解決這些問題CCR提出了自己的任務調度方案。DispatcherQueue。
DispatcherQueue本質上就是一個任務隊列,它使得任務按照先來後到的順序執行。但是你可以建立多個DispatcherQueue,比如把高優先順序的任務放入一個隊列,把普通優先順序的放入另外一個,那麼高優先順序的任務不需要等待前面所有普通優先順序任務都執行完畢才得到執行。
執行任務
Dispatcher是CCR的執行單元,也是一個線程池的實現。既然是線程池,那麼就必然有它所要管理的背景工作執行緒,TaskExecutionWorker類封裝了Dispatcher中背景工作執行緒所要執行的方法以及一些必要的處理。