예제 #1
0
        /// <summary>
        /// Attempt to steal work from the threadpool to execute it from the calling thread.
        /// If you absolutely have to block inside one of the threadpool's thread for whatever
        /// reason do a busy loop over this function.
        /// </summary>
        public bool TryCooperate()
        {
            if (workItems.TryDequeue(out var workItem))
            {
                Interlocked.Increment(ref threadsBusy);
                Interlocked.Decrement(ref workScheduled);
                try
                {
                    workItem.Invoke();
                }
                finally
                {
                    PooledDelegateHelper.Release(workItem);
                    Interlocked.Decrement(ref threadsBusy);
                    Interlocked.Increment(ref completionCounter);
                }
                return(true);
            }

            return(false);
        }
        private void ProcessWorkItems(object paramObj)
        {
            try
            {
                while (true)
                {
                    Action action;
                    var    sw = new SpinWait();
                    while (true)
                    {
                        if (queue.TryDequeue(out action))
                        {
                            break;
                        }

                        if (Volatile.Read(ref itemCount) == 0)
                        {
                            if (sw.NextSpinWillYield)
                            {
                                bool reset = false;
                                lock (lockObj)
                                {
                                    if (Volatile.Read(ref itemCount) == 0)
                                    {
                                        Interlocked.Increment(ref idleCount);
                                        Monitor.Wait(lockObj);
                                        // We've got work to deal with, pulse other threads
                                        Monitor.Pulse(lockObj);
                                        reset = true;
                                    }
                                }

                                if (reset)
                                {
                                    Interlocked.Decrement(ref idleCount);
                                    sw = new SpinWait();
                                }
                            }
                            else
                            {
                                // Spin for a while to catch more incoming work
                                sw.SpinOnce();
                            }
                        }
                    }

                    Interlocked.Decrement(ref itemCount);
                    try
                    {
                        action();
                    }
                    finally
                    {
                        PooledDelegateHelper.Release(action);
                    }
                }
            }
            finally
            {
                // We must keep up the amount of threads that the system handles.
                // Spawn a new one as this one is about to abort because of an exception.
                NewThread();
            }
        }