在前面介紹ACE主動對象中我已經簡單的介紹了一下主動對象模式,今天這裡我就簡單的介紹一下主動對象在C#中的實現。
所謂主動對象是相對於被動對象(passive object)而言的,被動對象的方法的調用和執行都是在同一個線程中的,被動對象方法的調用是同步的、阻塞的,一般的對象都屬於被動對象;主動對象的方法的調用和執行是分離的,主動對象有自己獨立的執行線程,主動對象的方法的調用是由其他線程發起的,但是方法是在自己的線程中執行的,主動對象方法的調用是非同步,非阻塞的。
本架構有如下幾部分構成:
- 一個ActiveObject類,從Thread繼承,封裝了並發邏輯的使用中的物件
- 一個ActiveQueue類,主要用來存放調用者請求
- 一個IMethodRequest介面,主要用來封裝調用者的請求,Command設計模式的一種實現方式
它們的一個簡單的實現如下:
interface IMethodRequest { void Call(); } class ActiveQueue<T> { const int maxCount = 10; //最大個 Queue<T> queue = new Queue<T>(); public void Enqueue(T item) { lock (this) { if (queue.Count >= maxCount) { Monitor.Wait(this); } queue.Enqueue(item); Monitor.PulseAll(this); } } public T Dequeue() { lock (this) { if (queue.Count == 0) { Monitor.Wait(this); } T item = queue.Dequeue(); Monitor.PulseAll(this); return item; } } } class ActiveObject { ActiveQueue<IMethodRequest> cmdQueue = new ActiveQueue<IMethodRequest>(); public ActiveObject() { ThreadPool.QueueUserWorkItem(ExcuteCommand); } public void AddCommand(IMethodRequest cmd) { cmdQueue.Enqueue(cmd); } private void ExcuteCommand(object obj) { while (true) { IMethodRequest cmd = cmdQueue.Dequeue(); cmd.Call(); } } } |
在主動對象的三個成員ActiveObject ,IMethodRequest,ActiveQueue中,前兩個都比較簡單,很容易想到實現的方法。稍微複雜一點的是ActiveQueue對象,它要求提供一個安全執行緒的操作類,這裡我仿照ACE利用Queue簡單的封裝了一個,為了使用簡單,我把它的Enqueue和Dequeue方法簡單的修改了一下。
- 當使用Enqueue方法時,如果隊列中的元素個數已經達到最大個數限制,將會阻塞至隊列中元素被Dequeue取走。
- 當使用Enqueue方法時,如果隊列中無可用元素,將會阻塞至其它線程通過Enqueue將元素插入至隊列中,然後返回可用元素。
我採用Monitor實現了這種線程同步,有興趣的朋友可以參看一下。
主動對象是一種常用的非同步通訊模式,這裡我簡單的給出了一種C#的實現。當然,我這裡的例子還不是很完善,更多知識可以看一下我以前介紹ACE主動對象的相關章節。