/// <summary> /// Blocks until all queued work is completed and then returns the results. /// </summary> /// <returns> /// The results of the work that was queued. /// </returns> /// <remarks> /// Calls to this method are serialized. /// </remarks> /// <exception cref='ObjectDisposedException'> /// Is thrown when this operation is performed after <see cref="Dispose"/> has been called. /// </exception> public IEnumerable <AsyncWorkResult <T> > GetResults() { if (IsDisposed) { throw new ObjectDisposedException(null); } // lock on the event itself to serialize calls to GetResults(). lock (_getResultsEvent) { // Wait for the signal from the work threads. _getResultsEvent.WaitOne(); // If new work is enqueue between the WaitOne() and here, make sure // it doesn't try to add to our results while we're copying them out. lock (_results) { // return a copy so no one mutates our internal state. AsyncWorkResult <T>[] copy = new AsyncWorkResult <T> [_results.Count]; _results.CopyTo(copy); _results.Clear(); return(copy); } } }
public IEnumerable <AsyncWorkResult <T> > GetResults() { AsyncWorkResult <T>[] copy = new AsyncWorkResult <T> [_results.Count]; _results.CopyTo(copy); _results.Clear(); return(copy); }
private void ProcessQueue() { while (!IsDisposed) { Interlocked.Increment(ref _waitingThreads); try { _workSync.WaitOne(); } finally { Interlocked.Decrement(ref _waitingThreads); } // Did we wake up because we're being disposed? if (IsDisposed) { break; } // Track that we're doing work now. Interlocked.Increment(ref _runningThreads); try { AsyncWorker <T> work; lock (_workQueue) work = _workQueue.Dequeue(); AsyncWorkResult <T> result; try { result = work(); } catch (Exception error) { result = new AsyncWorkResult <T>(error); } lock (_results) _results.Add(result); } finally { // Done doing work now Interlocked.Decrement(ref _runningThreads); } // is no one working now? if (_runningThreads == 0) { lock (_workQueue) // is there any work left? (double check no work has started since we // acquired the lock.) if (_workQueue.Count == 0 && _runningThreads == 0) { // Ok, looks like we're done here. Signal GetResults() _getResultsEvent.Set(); } } } }