internal static unsafe int WaitForSingleObject(IntPtr handle, int millisecondsTimeout) { SynchronizationContext context = RuntimeThread.CurrentThread.SynchronizationContext; bool useSyncContextWait = (context != null) && context.IsWaitNotificationRequired(); if (useSyncContextWait) { var handles = new IntPtr[1] { handle }; return(context.Wait(handles, false, millisecondsTimeout)); } return(WaitForMultipleObjectsIgnoringSyncContext(&handle, 1, false, millisecondsTimeout)); }
private bool WaitOneNoCheck(int millisecondsTimeout) { Debug.Assert(millisecondsTimeout >= -1); // The field value is modifiable via the public <see cref="WaitHandle.SafeWaitHandle"/> property, save it locally // to ensure that one instance is used in all places in this method SafeWaitHandle waitHandle = _waitHandle; if (waitHandle == null) { // Throw ObjectDisposedException for backward compatibility even though it is not be representative of the issue throw new ObjectDisposedException(null, SR.ObjectDisposed_Generic); } bool success = false; try { int waitResult; waitHandle.DangerousAddRef(ref success); SynchronizationContext context = SynchronizationContext.Current; if (context != null && context.IsWaitNotificationRequired()) { waitResult = context.Wait(new[] { waitHandle.DangerousGetHandle() }, false, millisecondsTimeout); } else { waitResult = WaitOneCore(waitHandle.DangerousGetHandle(), millisecondsTimeout); } if (waitResult == WaitAbandoned) { throw new AbandonedMutexException(); } return(waitResult != WaitTimeout); } finally { if (success) { waitHandle.DangerousRelease(); } } }
/*======================================================================== ** Waits for signal from all the objects. ** timeout indicates how long to wait before the method returns. ** This method will return either when all the object have been pulsed ** or timeout milliseonds have elapsed. ** ========================================================================*/ private static int WaitMultiple( RuntimeThread currentThread, SafeWaitHandle[] safeWaitHandles, int count, int millisecondsTimeout, bool waitAll) { Debug.Assert(currentThread == RuntimeThread.CurrentThread); Debug.Assert(safeWaitHandles != null); Debug.Assert(safeWaitHandles.Length >= count); // If we need to call SynchronizationContext.Wait method, always allocate a new IntPtr[] SynchronizationContext context = currentThread.SynchronizationContext; bool useSyncContextWait = (context != null) && context.IsWaitNotificationRequired(); IntPtr[] rentedHandles = useSyncContextWait ? null : currentThread.RentWaitedHandleArray(count); IntPtr[] handles = rentedHandles ?? new IntPtr[count]; try { for (int i = 0; i < count; i++) { handles[i] = safeWaitHandles[i].DangerousGetHandle(); } if (useSyncContextWait) { return(context.Wait(handles, waitAll, millisecondsTimeout)); } unsafe { fixed(IntPtr *pHandles = handles) { return(WaitForMultipleObjectsIgnoringSyncContext(pHandles, count, waitAll, millisecondsTimeout, true)); } } } finally { if (rentedHandles != null) { currentThread.ReturnWaitedHandleArray(rentedHandles); } } }
[System.Security.SecurityCritical] // auto-generated private static int InvokeWaitMethodHelper(SynchronizationContext syncContext, IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout) { return(syncContext.Wait(waitHandles, waitAll, millisecondsTimeout)); }
private static int WaitMultiple(ReadOnlySpan <WaitHandle> waitHandles, bool waitAll, int millisecondsTimeout) { if (waitHandles == null) { throw new ArgumentNullException(nameof(waitHandles), SR.ArgumentNull_Waithandles); } if (waitHandles.Length == 0) { // // Some history: in CLR 1.0 and 1.1, we threw ArgumentException in this case, which was correct. // Somehow, in 2.0, this became ArgumentNullException. This was not fixed until Silverlight 2, // which went back to ArgumentException. // // Now we're in a bit of a bind. Backward-compatibility requires us to keep throwing ArgumentException // in CoreCLR, and ArgumentNullException in the desktop CLR. This is ugly, but so is breaking // user code. // throw new ArgumentException(SR.Argument_EmptyWaithandleArray, nameof(waitHandles)); } if (waitHandles.Length > MaxWaitHandles) { throw new NotSupportedException(SR.NotSupported_MaxWaitHandles); } if (millisecondsTimeout < -1) { throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), SR.ArgumentOutOfRange_NeedNonNegOrNegative1); } SynchronizationContext context = SynchronizationContext.Current; bool useWaitContext = context != null && context.IsWaitNotificationRequired(); SafeWaitHandle[] safeWaitHandles = RentSafeWaitHandleArray(waitHandles.Length); try { int waitResult; if (useWaitContext) { IntPtr[] unsafeWaitHandles = new IntPtr[waitHandles.Length]; ObtainSafeWaitHandles(waitHandles, safeWaitHandles, unsafeWaitHandles); waitResult = context.Wait(unsafeWaitHandles, waitAll, millisecondsTimeout); } else { Span <IntPtr> unsafeWaitHandles = stackalloc IntPtr[waitHandles.Length]; ObtainSafeWaitHandles(waitHandles, safeWaitHandles, unsafeWaitHandles); waitResult = WaitMultipleIgnoringSyncContext(unsafeWaitHandles, waitAll, millisecondsTimeout); } if (waitResult >= WaitAbandoned && waitResult < WaitAbandoned + waitHandles.Length) { if (waitAll) { // In the case of WaitAll the OS will only provide the information that mutex was abandoned. // It won't tell us which one. So we can't set the Index or provide access to the Mutex throw new AbandonedMutexException(); } waitResult -= WaitAbandoned; throw new AbandonedMutexException(waitResult, waitHandles[waitResult]); } return(waitResult); } finally { for (int i = 0; i < waitHandles.Length; ++i) { if (safeWaitHandles[i] != null) { safeWaitHandles[i].DangerousRelease(); safeWaitHandles[i] = null; } } ReturnSafeWaitHandleArray(safeWaitHandles); } }
[System.Security.SecurityCritical] // auto-generated private static int InvokeWaitMethodHelper(SynchronizationContext syncContext, IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout) { return syncContext.Wait(waitHandles, waitAll, millisecondsTimeout); }