標籤:運行 生產者 view proc dynamic block exception rtp oid
這是從上文的<<圖文並茂的生產者消費者應用執行個體demo>>整理總結出來的,具體就不說了,直接給出代碼,注釋我已經加了,原來的code請看<<.Net中的並行編程-7.基於BlockingCollection實現高效能非同步隊列>>,我改成適合我的版本了,直接給code:
調用code:
static void Main(string[] args) { ProcessQueue<int> processQueue = new ProcessQueue<int>(); processQueue.ProcessExceptionEvent += ProcessQueue_ProcessExceptionEvent; processQueue.ProcessItemEvent += ProcessQueue_ProcessItemEvent; for (int i = 0; i < 50; i++) { processQueue.Enqueue(i); } Console.WriteLine("阻塞隊列的數量: {0}", processQueue.GetInternalItemCount()); processQueue.Flush(); Console.Read(); } /// <summary> /// 該方法對入隊的每個元素進行處理 /// </summary> /// <param name="value"></param> private static void ProcessQueue_ProcessItemEvent(int value) { Console.WriteLine("輸出: {0}", value); } /// <summary> /// 處理異常 /// </summary> /// <param name="obj">隊列執行個體</param> /// <param name="ex">異常對象</param> /// <param name="value">出錯的資料</param> private static void ProcessQueue_ProcessExceptionEvent(dynamic obj, Exception ex, int value) { Console.WriteLine(ex.ToString()); }
封裝的隊列:
public class ProcessQueue<T> { private BlockingCollection<T> _queue; private CancellationTokenSource _cancellationTokenSource; private CancellationToken _cancellToken; //內部線程池 private List<Thread> _threadCollection; //隊列是否正在處理資料 private int _isProcessing; //有線程正在處理資料 private const int Processing = 1; //沒有線程處理資料 private const int UnProcessing = 0; //隊列是否可用 private volatile bool _enabled = true; //內部處理線程數量 private int _internalThreadCount; // 消費者處理事件 public event Action<T> ProcessItemEvent; //處理異常,需要三個參數,當前隊列執行個體,異常,當時處理的資料 public event Action<dynamic, Exception, T> ProcessExceptionEvent; public ProcessQueue() { _queue = new BlockingCollection<T>(); _cancellationTokenSource = new CancellationTokenSource(); _internalThreadCount = 3; _cancellToken = _cancellationTokenSource.Token; _threadCollection = new List<Thread>(); } public ProcessQueue(int internalThreadCount) : this() { this._internalThreadCount = internalThreadCount; } /// <summary> /// 隊列內部元素的數量 /// </summary> public int GetInternalItemCount() { //return _queue.Count; return _threadCollection.Count; } //生產者生產 public void Enqueue(T items) { if (items == null) { throw new ArgumentException("items"); } _queue.Add(items); DataAdded(); } public void Flush() { StopProcess(); while (_queue.Count != 0) { T item = default(T); if (_queue.TryTake(out item)) { try { ProcessItemEvent(item); } catch (Exception ex) { OnProcessException(ex, item); } } } } // 通知消費者消費隊列元素 private void DataAdded() { if (_enabled) { if (!IsProcessingItem()) { Console.WriteLine("DataAdded"); ProcessRangeItem(); StartProcess(); } } } //判斷是否隊列有線程正在處理 private bool IsProcessingItem() { // 替換第一個參數, 如果相等 //int x = Interlocked.CompareExchange(ref _isProcessing, Processing, UnProcessing); return !(Interlocked.CompareExchange(ref _isProcessing, Processing, UnProcessing) == UnProcessing); } // 多消費者消費 private void ProcessRangeItem() { for (int i = 0; i < this._internalThreadCount; i++) { ProcessItem(); } } // 開啟消費處理 private void ProcessItem() { Thread currentThread = new Thread((state) => { T item = default(T); while (_enabled) { try { try { if (!_queue.TryTake(out item)) { //Console.WriteLine("阻塞隊列為0時的item: {0}", item); //Console.WriteLine("ok!!!"); break; } // 處理事件 ProcessItemEvent(item); } catch (OperationCanceledException ex) { DebugHelper.DebugView(ex.ToString()); } } catch (Exception ex) { OnProcessException(ex, item); } } }); _threadCollection.Add(currentThread); } // 開啟消費者 private void StartProcess() { //Console.WriteLine("線程的數量: {0}", _threadCollection.Count); foreach (var thread in _threadCollection) { thread.Start(); thread.IsBackground = true; } } // 終止運行 private void StopProcess() { this._enabled = false; foreach (var thread in _threadCollection) { if (thread.IsAlive) { thread.Join(); } } _threadCollection.Clear(); } private void OnProcessException(Exception ex, T item) { var tempException = ProcessExceptionEvent; Interlocked.CompareExchange(ref ProcessExceptionEvent, null, null); if (tempException != null) { ProcessExceptionEvent(this, ex, item); } } }
基於阻塞隊列的生產者消費者C#並發設計