// Inform the ThreadPool that there's work to be executed for this scheduler. private void NotifyThreadPoolOfPendingWork() { #if FEATURE_THREADPOOL_UNSAFEQUEUEWORKITEM ThreadPool.UnsafeQueueUserWorkItem( #else ThreadPool.QueueUserWorkItem( #endif _ => { // Note that the current thread is now processing work items. // This is necessary to enable inlining of tasks into this thread. _currentThreadIsProcessingItems = true; try { // Process all available items in the queue. while (true) { Task item; UninterruptableMonitor.Enter(_tasks); try { // When there are no more items to be processed, // note that we're done processing, and get out. if (_tasks.Count == 0) { --_delegatesQueuedOrRunning; break; } // Get the next item from the queue item = _tasks.First.Value; _tasks.Remove(item); } finally { UninterruptableMonitor.Exit(_tasks); } // Execute the task we pulled out of the queue base.TryExecuteTask(item); } } // We're done processing items on the current thread finally { _currentThreadIsProcessingItems = false; } }, null); }
// Gets an enumerable of the tasks currently scheduled on this scheduler. protected sealed override IEnumerable <Task> GetScheduledTasks() { bool lockTaken = false; try { UninterruptableMonitor.TryEnter(_tasks, ref lockTaken); if (lockTaken) { return(_tasks); } else { throw new NotSupportedException(); } } finally { if (lockTaken) { UninterruptableMonitor.Exit(_tasks); } } }
// .NET Port: mimic ReentrantLock -- Monitor is re-entrant public void Unlock() { UninterruptableMonitor.Exit(_lock); }