internal static bool Dispatch()
        {
            ThreadPoolWorkQueue workQueue = ThreadPoolGlobals.workQueue;
            int tickCount = Environment.TickCount;

            workQueue.MarkThreadRequestSatisfied();
            workQueue.loggingEnabled = FrameworkEventSource.Log.IsEnabled(EventLevel.Verbose, (EventKeywords)18L);
            bool flag = true;
            IThreadPoolWorkItem threadPoolWorkItem = null;

            try
            {
                ThreadPoolWorkQueueThreadLocals tl = workQueue.EnsureCurrentThreadHasQueue();
                while ((long)(Environment.TickCount - tickCount) < (long)((ulong)ThreadPoolGlobals.tpQuantum))
                {
                    try
                    {
                    }
                    finally
                    {
                        bool flag2 = false;
                        workQueue.Dequeue(tl, out threadPoolWorkItem, out flag2);
                        if (threadPoolWorkItem == null)
                        {
                            flag = flag2;
                        }
                        else
                        {
                            workQueue.EnsureThreadRequested();
                        }
                    }
                    if (threadPoolWorkItem == null)
                    {
                        return(true);
                    }
                    if (workQueue.loggingEnabled)
                    {
                        FrameworkEventSource.Log.ThreadPoolDequeueWorkObject(threadPoolWorkItem);
                    }
                    if (ThreadPoolGlobals.enableWorkerTracking)
                    {
                        bool flag3 = false;
                        try
                        {
                            try
                            {
                            }
                            finally
                            {
                                ThreadPool.ReportThreadStatus(true);
                                flag3 = true;
                            }
                            threadPoolWorkItem.ExecuteWorkItem();
                            threadPoolWorkItem = null;
                            goto IL_A6;
                        }
                        finally
                        {
                            if (flag3)
                            {
                                ThreadPool.ReportThreadStatus(false);
                            }
                        }
                        goto IL_9E;
                    }
                    goto IL_9E;
IL_A6:
                    if (!ThreadPool.NotifyWorkItemComplete())
                    {
                        return(false);
                    }
                    continue;
IL_9E:
                    threadPoolWorkItem.ExecuteWorkItem();
                    threadPoolWorkItem = null;
                    goto IL_A6;
                }
                return(true);
            }
            catch (ThreadAbortException tae)
            {
                if (threadPoolWorkItem != null)
                {
                    threadPoolWorkItem.MarkAborted(tae);
                }
                flag = false;
            }
            finally
            {
                if (flag)
                {
                    workQueue.EnsureThreadRequested();
                }
            }
            return(true);
        }
Пример #2
0
        internal static bool Dispatch()
        {
            ThreadPoolWorkQueue threadPoolWorkQueue = ThreadPoolGlobals.workQueue;
            int tickCount = Environment.TickCount;

            threadPoolWorkQueue.MarkThreadRequestSatisfied();
            threadPoolWorkQueue.loggingEnabled = FrameworkEventSource.Log.IsEnabled(EventLevel.Verbose, (EventKeywords)18);
            bool flag1 = true;
            IThreadPoolWorkItem callback = (IThreadPoolWorkItem)null;

            try
            {
                ThreadPoolWorkQueueThreadLocals tl = threadPoolWorkQueue.EnsureCurrentThreadHasQueue();
                while ((long)(Environment.TickCount - tickCount) < (long)ThreadPoolGlobals.tpQuantum)
                {
                    try
                    {
                    }
                    finally
                    {
                        bool missedSteal = false;
                        threadPoolWorkQueue.Dequeue(tl, out callback, out missedSteal);
                        if (callback == null)
                        {
                            flag1 = missedSteal;
                        }
                        else
                        {
                            threadPoolWorkQueue.EnsureThreadRequested();
                        }
                    }
                    if (callback == null)
                    {
                        return(true);
                    }
                    if (threadPoolWorkQueue.loggingEnabled)
                    {
                        FrameworkEventSource.Log.ThreadPoolDequeueWorkObject((object)callback);
                    }
                    if (ThreadPoolGlobals.enableWorkerTracking)
                    {
                        bool flag2 = false;
                        try
                        {
                            try
                            {
                            }
                            finally
                            {
                                ThreadPool.ReportThreadStatus(true);
                                flag2 = true;
                            }
                            callback.ExecuteWorkItem();
                            callback = (IThreadPoolWorkItem)null;
                        }
                        finally
                        {
                            if (flag2)
                            {
                                ThreadPool.ReportThreadStatus(false);
                            }
                        }
                    }
                    else
                    {
                        callback.ExecuteWorkItem();
                        callback = (IThreadPoolWorkItem)null;
                    }
                    if (!ThreadPool.NotifyWorkItemComplete())
                    {
                        return(false);
                    }
                }
                return(true);
            }
            catch (ThreadAbortException ex)
            {
                if (callback != null)
                {
                    callback.MarkAborted(ex);
                }
                flag1 = false;
            }
            finally
            {
                if (flag1)
                {
                    threadPoolWorkQueue.EnsureThreadRequested();
                }
            }
            return(true);
        }
Пример #3
0
        /// <summary>
        /// Dispatches work items to this thread.
        /// </summary>
        /// <returns>
        /// <c>true</c> if this thread did as much work as was available or its quantum expired.
        /// <c>false</c> if this thread stopped working early.
        /// </returns>
        internal static bool Dispatch()
        {
            ThreadPoolWorkQueue outerWorkQueue = ThreadPoolGlobals.workQueue;

            //
            // Save the start time
            //
            int startTickCount = Environment.TickCount;

            //
            // Update our records to indicate that an outstanding request for a thread has now been fulfilled.
            // From this point on, we are responsible for requesting another thread if we stop working for any
            // reason, and we believe there might still be work in the queue.
            //
            outerWorkQueue.MarkThreadRequestSatisfied();

            Interlocked.Increment(ref outerWorkQueue.numWorkingThreads);

            //
            // Assume that we're going to need another thread if this one returns to the VM.  We'll set this to
            // false later, but only if we're absolutely certain that the queue is empty.
            //
            bool   needAnotherThread = true;
            object outerWorkItem     = null;

            try
            {
                //
                // Set up our thread-local data
                //
                // Use operate on workQueue local to try block so it can be enregistered
                ThreadPoolWorkQueue             workQueue = outerWorkQueue;
                ThreadPoolWorkQueueThreadLocals tl        = workQueue.GetOrCreateThreadLocals();
                Thread currentThread = tl.currentThread;

                // Start on clean ExecutionContext and SynchronizationContext
                currentThread.ExecutionContext       = null;
                currentThread.SynchronizationContext = null;

                //
                // Loop until our quantum expires or there is no work.
                //
                while (ThreadPool.KeepDispatching(startTickCount))
                {
                    bool missedSteal = false;
                    // Use operate on workItem local to try block so it can be enregistered
                    object workItem = outerWorkItem = workQueue.Dequeue(tl, ref missedSteal);

                    if (workItem == null)
                    {
                        //
                        // No work.
                        // If we missed a steal, though, there may be more work in the queue.
                        // Instead of looping around and trying again, we'll just request another thread.  Hopefully the thread
                        // that owns the contended work-stealing queue will pick up its own workitems in the meantime,
                        // which will be more efficient than this thread doing it anyway.
                        //
                        needAnotherThread = missedSteal;

                        // Tell the VM we're returning normally, not because Hill Climbing asked us to return.
                        return(true);
                    }

                    //
                    // If we found work, there may be more work.  Ask for another thread so that the other work can be processed
                    // in parallel.  Note that this will only ask for a max of #procs threads, so it's safe to call it for every dequeue.
                    //
                    workQueue.EnsureThreadRequested();

                    if (workItem is Task task)
                    {
                        task.ExecuteFromThreadPool(currentThread);
                    }
                    else
                    {
                        Debug.Assert(workItem is IThreadPoolWorkItem);
                        Unsafe.As <IThreadPoolWorkItem>(workItem).Execute();
                    }

                    RuntimeThread.CurrentThread.ResetThreadPoolThread();

                    // Release refs
                    outerWorkItem = workItem = null;

                    // Return to clean ExecutionContext and SynchronizationContext
                    ExecutionContext.ResetThreadPoolThread(currentThread);

                    if (!ThreadPool.NotifyWorkItemComplete())
                    {
                        return(false);
                    }
                }

                // If we get here, it's because our quantum expired.
                return(true);
            }
            catch (Exception e)
            {
                // Work items should not allow exceptions to escape.  For example, Task catches and stores any exceptions.
                Environment.FailFast("Unhandled exception in ThreadPool dispatch loop", e);
                return(true); // Will never actually be executed because Environment.FailFast doesn't return
            }
            finally
            {
                int numWorkers = Interlocked.Decrement(ref outerWorkQueue.numWorkingThreads);
                Debug.Assert(numWorkers >= 0);

                //
                // If we are exiting for any reason other than that the queue is definitely empty, ask for another
                // thread to pick up where we left off.
                //
                if (needAnotherThread)
                {
                    outerWorkQueue.EnsureThreadRequested();
                }
            }
        }