/// <summary>Releases the lock on an object and blocks the current thread until it reacquires the lock. If the specified time-out interval elapses, the thread enters the ready queue.</summary> /// <returns>true if the lock was reacquired before the specified time elapsed; false if the lock was reacquired after the specified time elapsed. The method does not return until the lock is reacquired.</returns> /// <param name="obj">The object on which to wait. </param> /// <param name="millisecondsTimeout">The number of milliseconds to wait before the thread enters the ready queue. </param> /// <exception cref="T:System.ArgumentNullException">The <paramref name="obj" /> parameter is null. </exception> /// <exception cref="T:System.Threading.SynchronizationLockException">The calling thread does not own the lock for the specified object. </exception> /// <exception cref="T:System.Threading.ThreadInterruptedException">The thread that invokes Wait is later interrupted from the waiting state. This happens when another thread calls this thread's <see cref="M:System.Threading.Thread.Interrupt" /> method. </exception> /// <exception cref="T:System.ArgumentOutOfRangeException">The value of the <paramref name="millisecondsTimeout" /> parameter is negative, and is not equal to <see cref="F:System.Threading.Timeout.Infinite" />. </exception> /// <filterpriority>1</filterpriority> public static bool Wait(object obj, int millisecondsTimeout) { if (obj == null) { throw new ArgumentNullException("obj"); } if (millisecondsTimeout < -1) { throw new ArgumentOutOfRangeException("millisecondsTimeout", "timeout out of range"); } if (!Monitor.Monitor_test_synchronised(obj)) { throw new SynchronizationLockException("Object is not synchronized"); } return(Monitor.Monitor_wait(obj, millisecondsTimeout)); }
private bool WaitCore(int timeoutMs) { WaitEntry wait_entry = new WaitEntry(); bool mutexLocked = false; bool waitEntryLocked = false; try { Monitor.try_enter_with_atomic_var(mutex, Timeout.Infinite, false, ref mutexLocked); if (pending_signals > 0) { --pending_signals; return(true); } wait_entry.condition = new object(); wait_entry.previous = null; wait_entry.next = head; if (head != null) { Unsafe.AsRef <WaitEntry> (head).previous = Unsafe.AsPointer <WaitEntry> (ref wait_entry); } head = Unsafe.AsPointer <WaitEntry> (ref wait_entry); } finally { if (mutexLocked) { Monitor.Exit(mutex); } } try { Monitor.try_enter_with_atomic_var(wait_entry.condition, Timeout.Infinite, false, ref waitEntryLocked); if (!wait_entry.signaled) { Monitor.Monitor_wait(wait_entry.condition, timeoutMs, false); } } finally { if (waitEntryLocked) { Monitor.Exit(wait_entry.condition); } } mutexLocked = false; try { Monitor.try_enter_with_atomic_var(mutex, Timeout.Infinite, false, ref mutexLocked); if (!wait_entry.signaled) { if (head == Unsafe.AsPointer <WaitEntry> (ref wait_entry)) { head = wait_entry.next; } if (wait_entry.next != null) { Unsafe.AsRef <WaitEntry> (wait_entry.next).previous = wait_entry.previous; } if (wait_entry.previous != null) { Unsafe.AsRef <WaitEntry> (wait_entry.previous).next = wait_entry.next; } } } finally { if (mutexLocked) { Monitor.Exit(mutex); } } return(wait_entry.signaled); }