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); }
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); }
/// <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(); } } }