HowTo Asynchronous Worker Process
From Frederick Chapleau Wiki
Overview
This is based on the HowTo DesignPattern Singleton article.
After a call to AsyncProcessor.Instance.Start(); the processor will start, and a call to AsyncProcessor.Instance.Queue(theIdToProcess); will queue the request that is, in that context, a simple GUID.
Source
public class AsyncProcessor { #region Singleton /// <summary> /// Private static variable representing the single intance of the class /// </summary> private static AsyncProcessor _instance; /// <summary> /// This constructor is private, so, the only class that can create it, is... me. /// </summary> private AsyncProcessor() { } /// <summary> /// The Instance public property is the accessor to the single instance of the /// class. This is static because the constructor is private, so it's the only way to /// access a property /// </summary> public static AsyncProcessor Instance { get { // if the instance is not yet created, if (_instance == null) { // We create the only intance of our self _instance = new AsyncProcessor(); _instance._processingObjects = new Queue<Guid>(); } // and we return the only instance return _instance; } } #endregion private Thread _asyncProcessing; private Queue<Guid> _processingObjects; public void Start() { ThreadStart ts = new ThreadStart(AsyncStart); _asyncProcessing = new Thread(ts); _asyncProcessing.Name = "Asynchronous Processing"; _asyncProcessing.IsBackground = true; _asyncProcessing.Start(); } public void AsyncStart() { while (true) { bool processed = false; Guid currentId = Guid.Empty; // Here we lock the queue to check if there is something to process Monitor.Enter(_asyncProcessing); if (_processingObjects.Count > 0) { // Here we just peek the next object // The object will remain in the queue until a dequeue is done. currentId = _processingObjects.Peek(); } Monitor.Exit(_asyncProcessing); if (currentId != Guid.Empty) { try { // *********** // TODO: Implement the logic to process the ID // *********** // process the current id processed = true; // Now that the process is done, we remove the id from the queue Monitor.Enter(_asyncProcessing); _processingObjects.Dequeue(); Monitor.Exit(_asyncProcessing); } catch { // Error Handling, here we just sleep & retry the same object (the peek didn't release it) } } // if something was processed we wait less, just to throttle processing // else we wait longer. if(processed) Thread.Sleep(100); else Thread.Sleep(1000); } } public void Queue(Guid id) { Monitor.Enter(_processingObjects); _processingObjects.Enqueue(id); Monitor.Exit(_processingObjects); } }

