// Add a work item to the worker queue. private static void AddWorkItem(WorkItem item) { if (!Thread.CanStartThreads()) { // Add the item to the end of the worker queue. if (lastWorkItem != null) { lastWorkItem.next = item; } else { workItems = item; } lastWorkItem = item; // We don't have threads, so execute the items now. WorkItem next = ItemToDispatch(); while (next != null) { next.Execute(); next = ItemToDispatch(); } } else { lock (typeof(ThreadPool)) { if (lastWorkItem != null) { lastWorkItem.next = item; } else { workItems = item; } lastWorkItem = item; // Determine if we need to spawn a new worker thread. if (workItems != null && numWorkerThreads < MaxWorkerThreads) { if (workerThreads == null) { workerThreads = new Thread [MaxWorkerThreads]; } Thread thread = new Thread(new ThreadStart(Work)); #if !ECMA_COMPAT thread.inThreadPool = true; #endif workerThreads[numWorkerThreads++] = thread; thread.IsBackground = true; thread.Start(); } Monitor.Pulse(typeof(ThreadPool)); } } }
// Run a worker thread. private static void Work() { // Assert unrestricted permissions for this thread. // The permissions will be modified for each work item // to reflect the context that created the work item. ClrSecurity.SetPermissions(null, 0); // Wait for and dispatch work items. WorkItem item = null; for (;;) { lock (typeof(ThreadPool)) { do { item = ItemToDispatch(); if (item == null) { Monitor.Wait(typeof(ThreadPool)); } }while(item == null); } try { Interlocked.Increment(ref usedWorkerThreads); item.Execute(); } finally { item = null; Interlocked.Decrement(ref usedWorkerThreads); } } }
// Add a work item to the completion queue. private static void AddCompletionItem(WorkItem item) { if (!Thread.CanStartThreads()) { // Add the item to the end of the worker queue. if (lastCompletionItem != null) { lastCompletionItem.next = item; } else { completionItems = item; } lastCompletionItem = item; // We don't have threads, so execute the items now. WorkItem next = CompletionItemToDispatch(); while (next != null) { next.Execute(); next = CompletionItemToDispatch(); } } else { lock (completionWait) { if (lastCompletionItem != null) { lastCompletionItem.next = item; } else { completionItems = item; } lastCompletionItem = item; queuedCompletionItems++; if (completionThreads == null) { completionThreads = new Thread [MaxCompletionThreads]; } // // We need to make sure that there are enough threads to // handle the entire queue. // // There is a small possibility here that there is a thread // about to end that could take this work unit, but we have no // way of knowing that. // int needThreads = usedCompletionThreads + queuedCompletionItems; // Determine if we need to spawn a new completion thread. if (needThreads > numCompletionThreads) { if (needThreads > MaxCompletionThreads) // throw new SystemException("Number of completion threads required exceeds maximum"); { // Don't throw. Leave on the queue and pulse the lock if there are any waiting threads if (usedCompletionThreads < numCompletionThreads) { Monitor.Pulse(completionWait); } return; } Thread thread = new Thread(new ThreadStart(Complete)); #if !ECMA_COMPAT thread.inThreadPool = true; #endif completionThreads[numCompletionThreads++] = thread; thread.IsBackground = true; thread.Start(); } else { // Signal one of our waiting threads Monitor.Pulse(completionWait); } } } }