public void TestComplexMonitor() { this.Test(async() => { object syncObject = new object(); bool waiting = false; List <string> log = new List <string>(); Task t1 = Task.Run(() => { Monitor.Enter(syncObject); log.Add("waiting"); waiting = true; Monitor.Wait(syncObject); log.Add("received pulse"); Monitor.Exit(syncObject); }); Task t2 = Task.Run(async() => { while (!waiting) { await Task.Delay(1); } Monitor.Enter(syncObject); Monitor.Pulse(syncObject); log.Add("pulsed"); Monitor.Exit(syncObject); }); await Task.WhenAll(t1, t2); string expected = "waiting, pulsed, received pulse"; string actual = string.Join(", ", log); Specification.Assert(expected == actual, "ControlledMonitor out of order, '{0}' instead of '{1}'", actual, expected); }, this.GetConfiguration()); }
/// <summary> /// Notifies a thread in the waiting queue of a change in the locked object's state. /// </summary> public virtual void Pulse() => SystemMonitor.Pulse(this.SyncObject);
/// <summary> /// Notifies a thread in the waiting queue of a change in the locked object's state. /// </summary> internal virtual void Pulse() => SystemMonitor.Pulse(this.SyncObject);
// 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); } } } }