/// <summary>Queues a user work item to the thread pool.</summary> /// <param name="callback"> /// A WaitCallback representing the delegate to invoke when the thread in the /// thread pool picks up the work item. /// </param> /// <param name="state"> /// The object that is passed to the delegate when serviced from the thread pool. /// </param> /// <param name="priority">The priority for this callback.</param> public void QueueUserWorkItem(WaitCallback callback, object state, int priority) { // Create a waiting callback that contains the delegate and its state. // At it to the processing queue, and signal that data is waiting. PriorityThreadPool.WaitingCallback waiting = new PriorityThreadPool.WaitingCallback(callback, state); lock (_waitingCallbacks.SyncRoot) { _waitingCallbacks.Enqueue(priority, waiting); } _workerThreadNeeded.AddOne(); }
/// <summary>A thread worker function that processes items from the work queue.</summary> private void ProcessQueuedItems() { // Process indefinitely while (true) { // Get the next item in the queue. If there is nothing there, go to sleep // for a while until we're woken up when a callback is waiting. PriorityThreadPool.WaitingCallback callback = null; while (callback == null) { // Try to get the next callback available. We need to lock on the // queue in order to make our count check and retrieval atomic. lock (_waitingCallbacks.SyncRoot) { if (_waitingCallbacks.Count > 0) { callback = (PriorityThreadPool.WaitingCallback)_waitingCallbacks.Dequeue(); } } // If we can't get one, go to sleep. if (callback == null) { _workerThreadNeeded.WaitOne(); } } // We now have a callback. Execute it. Make sure to accurately // record how many callbacks are currently executing. try { Interlocked.Increment(ref _inUseThreads); callback.Callback(callback.State); } catch (System.Exception) { // Ignore any errors; not our problem. } finally { Interlocked.Decrement(ref _inUseThreads); } } }