Three years ago, the Concurrentqueue -based asynchronous queue was written, and today, while collating the code, found another way to implement it--using the BlockingCollection implementation, which is still being used in actual projects. For basic use of blockingcollection, please refer to MSDN. Source Code Implementation
The code is directly below: (The code is already on my github)
usingSystem;usingSystem.Collections.Concurrent;usingSystem.Collections.Generic;usingSystem.Threading;usingDanny.Infrastructure.Helper;namespacedanny.infrastructure.collections{/// <summary> ///a multi-threaded processing queue based on the BlockingCollection implementation/// </summary> Public classProcessqueue<t> { PrivateBlockingcollection<t>_queue; PrivateCancellationTokenSource _cancellationtokensource; PrivateCancellationToken _cancelltoken; //Internal thread pool PrivateList<thread>_threadcollection; //whether the queue is processing data Private int_isprocessing; //Wired is impersonating to process data Private Const intProcessing =1; //no thread processing data Private Const intUnprocessing =0; //whether the queue is available Private volatile BOOL_enabled =true; //number of internal processing threads Private int_internalthreadcount; Public EventAction<t>processitemevent; //handling exceptions, requires three parameters, current queue instance, exception, data processed at that time Public Eventaction<Dynamic,exception,t>processexceptionevent; PublicProcessqueue () {_queue=NewBlockingcollection<t>(); _cancellationtokensource=NewCancellationTokenSource (); _internalthreadcount=1; _cancelltoken=_cancellationtokensource.token; _threadcollection=NewList<thread>(); } PublicProcessqueue (intInternalthreadcount): This() { This. _internalthreadcount =Internalthreadcount; } /// <summary> ///number of internal elements in the queue/// </summary> Public intGetinternalitemcount () {return_queue. Count; } Public voidEnqueue (T items) {if(Items = =NULL) { Throw NewArgumentException ("Items"); } _queue. ADD (items); Dataadded (); } Public voidFlush () {stopprocess (); while(_queue. Count! =0) {T Item=default(T); if(_queue. TryTake ( outitem)) { Try{processitemevent (item); } Catch(Exception ex) {onprocessexception (Ex,item); } } } } Private voiddataadded () {if(_enabled) {if(!Isprocessingitem ()) {Processrangeitem (); StartProcess (); } } } //determine if the queue is wired is impersonating in the processing Private BOOLIsprocessingitem () {return! (Interlocked.compareexchange (ref_isprocessing, processing, unprocessing) = =unprocessing); } Private voidProcessrangeitem () { for(inti =0; I < This. _internalthreadcount; i++) {Processitem (); } } Private voidProcessitem () {Thread CurrentThread=NewThread (state) ={T Item=default(T); while(_enabled) {Try { Try{Item=_queue. Take (_cancelltoken); processItemEvent (item); } Catch(OperationCanceledException ex) {Debughelper.debugview (ex). ToString ()); } } Catch(Exception ex) {onprocessexception (Ex,item); } } }); _threadcollection.add (CurrentThread); } Private voidstartprocess () {foreach(varThreadinch_threadcollection) {Thread. Start (); } } Private voidstopprocess () { This. _enabled =false; foreach(varThreadinch_threadcollection) { if(thread. IsAlive) {thread. Join (); }} _threadcollection.clear (); } Private voidonprocessexception (Exception ex,t item) {varTempexception =processexceptionevent; Interlocked.compareexchange (refProcessexceptionevent,NULL,NULL); if(Tempexception! =NULL) {processexceptionevent ( This, Ex,item); } } }}
How to use:
classProgram {Static voidMain (string[] args) {Processqueue<int> processqueue =Newprocessqueue<int>(); Processqueue.processexceptionevent+=processqueue_processexceptionevent; Processqueue.processitemevent+=processqueue_processitemevent; Processqueue.enqueue (1); Processqueue.enqueue (2); Processqueue.enqueue (3); } /// <summary> ///This method processes each element of the queue/// </summary> /// <param name= "value" ></param> Private Static voidProcessqueue_processitemevent (intvalue) {Console.WriteLine (value); } /// <summary> ///Handling Exceptions/// </summary> /// <param name= "obj" >Queue Instances</param> /// <param name= "ex" >Exception Object</param> /// <param name= "value" >Data in error</param> Private Static voidProcessqueue_processexceptionevent (Dynamicobj, Exception ex,intvalue) {Console.WriteLine (ex. ToString ()); } }
. NET parallel Programming-7. Implementing high-performance asynchronous queues based on BlockingCollection