コード例 #1
0
        /// <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);
                }
            }
        }
コード例 #2
0
        public IEnumerable <AsyncWorkResult <T> > GetResults()
        {
            AsyncWorkResult <T>[] copy = new AsyncWorkResult <T> [_results.Count];
            _results.CopyTo(copy);
            _results.Clear();

            return(copy);
        }
コード例 #3
0
        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();
                        }
                }
            }
        }