Producer consumer C # Concurrent Design Based on blocking queue,
This is summarized from the preceding <demo of the consumer app of illustrated images and texts>. If you don't want to mention it, You can directly provide the code and add comments, for the original code, see <. net parallel programming-7. high-performance asynchronous Queue Based on BlockingCollection>, I changed it to a suitable version, directly to the code:
Call 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 ("Number of blocked Queues: {0}", processQueue. getInternalItemCount (); processQueue. flush (); Console. read ();} /// <summary> /// this method processes each element of the queue. /// </summary> /// <param name = "value"> </param> private static void ProcessQueue_ProcessItemEvent (int value) {Console. writeLine ("output: {0}", value );} /// <summary> /// handle exceptions /// </summary> /// <param name = "obj"> queue instance </param> /// <param name = "ex"> exception object </param> // <param name = "value"> Error Data </param> private static void ProcessQueue_ProcessExceptionEvent (dynamic obj, exception ex, int value) {Console. writeLine (ex. toString ());}
Encapsulated queue:
Public class ProcessQueue <T> {private BlockingCollection <T> _ queue; private CancellationTokenSource _ cancellationTokenSource; private CancellationToken _ cancellToken; // private List of Internal Thread pools <Thread> _ threadCollection; // whether the queue is Processing data private int _ isProcessing; // a thread is Processing data private const int Processing = 1; // no thread is Processing data private const int UnProcessing = 0; // whether the queue is available private volatile bool _ enabled = true; // internal Number of processing threads private int _ internalThreadCount; // The Consumer processes the event public event Action <T> ProcessItemEvent; // The exception is handled. Three parameters are required for the current queue instance. An exception occurs, public event Action <dynamic, Exception, T> ProcessExceptionEvent; public ProcessQueue () {_ queue = new BlockingCollection <T> (); _ cancellationTokenSource = new CancellationTokenSource (); _ internalThreadCount = 3; _ cancellToken = _ cancellationTokenSource. token; _ threadCollecti On = new List <Thread> ();} public ProcessQueue (int internalThreadCount): this () {this. _ internalThreadCount = internalThreadCount;} // <summary> // number of elements in the queue /// </summary> public int GetInternalItemCount () {// return _ queue. count; return _ threadCollection. count;} // producer produces 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 );}}}} // notify the consumer of the consumption queue element private void DataAdded () {if (_ enabled) {if (! IsProcessingItem () {Console. writeLine ("DataAdded"); ProcessRangeItem (); StartProcess () ;}}// determine whether a thread in the queue is processing private bool IsProcessingItem () {// Replace the first parameter, if it is equal // int x = Interlocked. compareExchange (ref _ isProcessing, Processing, UnProcessing); return! (Interlocked. compareExchange (ref _ isProcessing, Processing, UnProcessing) = UnProcessing);} // multiple consumers consume private void ProcessRangeItem () {for (int I = 0; I <this. _ internalThreadCount; I ++) {ProcessItem () ;}// enable consumption Processing private void ProcessItem () {Thread currentThread = new Thread (state) ==>{ T item = default (T); while (_ enabled) {try {if (! _ Queue. tryTake (out item) {// Console. writeLine ("item: {0} when the blocking queue is 0", item); // Console. writeLine ("OK !!! "); Break;} // process event ProcessItemEvent (item);} catch (OperationCanceledException ex) {DebugHelper. debugView (ex. toString () ;}} catch (Exception ex) {OnProcessException (ex, item) ;}}); _ threadCollection. add (currentThread);} // enable the consumer private void StartProcess () {// Console. writeLine ("Number of threads: {0}", _ threadCollection. count); foreach (var thread in _ threadCollection) {thread. start (); thread. isBac Kground = true ;}// terminate the 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 );}}}