Parallel Programming in. Net-7. High-Performance asynchronous queue and High-Performance Parallel Computing Based on BlockingCollection
Based onConcurrentQueueThe asynchronous queue of. Today, we found another implementation method-BlockingCollection implementation, which is still used in actual projects. For basic use of BlockingCollection, refer to MSDN. Source code implementation
The following code is directly used: (the code has been put on my github)
Using System; using System. collections. concurrent; using System. collections. generic; using System. threading; using Danny. infrastructure. helper; namespace Danny. infrastructure. collections {/// <summary> /// a multi-threaded processing queue based on BlockingCollection /// </summary> public class ProcessQueue <T> {private BlockingCollection <T> _ queue; private CancellationTokenSource _ cancellationTokenSource; private CancellationToke N _ cancellToken; // Internal Thread Pool private List <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; // number of internal processing threads private int _ internalThreadCount; public event Action <T> ProcessItemEvent; // handle an exception. Three parameters are required: current queue instance, exception, public event Action <dynamic, effectio N, T> ProcessExceptionEvent; public ProcessQueue () {_ queue = new BlockingCollection <T> (); _ cancellationTokenSource = new CancellationTokenSource (); _ internalThreadCount = 1; _ cancellToken = _ cancellationTokenSource. token; _ threadCollection = new List <Thread> ();} public ProcessQueue (int internalThreadCount): this () {this. _ internalThreadCount = internalThreadCount;} // <summary> // number of internal elements in the queue /// </Summary> public int GetInternalItemCount () {return _ queue. 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 () {ProcessRangeItem (); StartProcess () ;}}// determine whether a thread in the queue is processing private bool IsProcessingItem () {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 {item = _ queue. take (_ cancellToken); ProcessItemEvent (item);} catch (Operat IonCanceledException ex) {DebugHelper. debugView (ex. toString () ;}} catch (Exception ex) {OnProcessException (ex, item) ;}}); _ threadCollection. add (currentThread);} private void StartProcess () {foreach (var thread in _ threadCollection) {thread. start () ;}} 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 );}}}}
Usage:
Class Program {static void Main (string [] args) {ProcessQueue <int> processQueue = new ProcessQueue <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 void ProcessQueue_ProcessItemEvent (int value) {Console. writeLine (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 ());}}