/// <summary> /// Unregisters this wait handle registration from the wait threads. /// </summary> /// <param name="waitObject">The event to signal when the handle is unregistered.</param> /// <returns>If the handle was successfully marked to be removed and the provided wait handle was set as the user provided event.</returns> /// <remarks> /// This method will only return true on the first call. /// Passing in a wait handle with a value of -1 will result in a blocking wait, where Unregister will not return until the full unregistration is completed. /// </remarks> public bool Unregister(WaitHandle?waitObject) { GC.SuppressFinalize(this); _callbackLock.Acquire(); bool needToRollBackRefCountOnException = false; try { if (_unregisterCalled) { return(false); } UserUnregisterWaitHandle = waitObject?.SafeWaitHandle; UserUnregisterWaitHandle?.DangerousAddRef(ref needToRollBackRefCountOnException); UserUnregisterWaitHandleValue = UserUnregisterWaitHandle?.DangerousGetHandle() ?? IntPtr.Zero; if (_unregistered) { SignalUserWaitHandle(); return(true); } if (IsBlocking) { _callbacksComplete = RentEvent(); } else { _removed = RentEvent(); } _unregisterCalled = true; } catch (Exception) // Rollback state on exception { if (_removed != null) { ReturnEvent(_removed); _removed = null; } else if (_callbacksComplete != null) { ReturnEvent(_callbacksComplete); _callbacksComplete = null; } UserUnregisterWaitHandleValue = IntPtr.Zero; if (needToRollBackRefCountOnException) { UserUnregisterWaitHandle?.DangerousRelease(); } UserUnregisterWaitHandle = null; throw; } finally { _callbackLock.Release(); } WaitThread !.UnregisterWait(this); return(true); }
public bool Unregister(WaitHandle waitObject) { // The registered wait handle must have been registered by this time, otherwise the instance is not handed out to // the caller of the public variants of RegisterWaitForSingleObject Debug.Assert(WaitThread != null); s_callbackLock.Acquire(); bool needToRollBackRefCountOnException = false; try { if (_unregisterCalled) { return(false); } UserUnregisterWaitHandle = waitObject?.SafeWaitHandle; UserUnregisterWaitHandle?.DangerousAddRef(ref needToRollBackRefCountOnException); UserUnregisterWaitHandleValue = UserUnregisterWaitHandle?.DangerousGetHandle() ?? IntPtr.Zero; if (_unregistered) { SignalUserWaitHandle(); return(true); } if (IsBlocking) { _callbacksComplete = RentEvent(); } else { _removed = RentEvent(); } } catch (Exception) // Rollback state on exception { if (_removed != null) { ReturnEvent(_removed); _removed = null; } else if (_callbacksComplete != null) { ReturnEvent(_callbacksComplete); _callbacksComplete = null; } UserUnregisterWaitHandleValue = IntPtr.Zero; if (needToRollBackRefCountOnException) { UserUnregisterWaitHandle?.DangerousRelease(); } UserUnregisterWaitHandle = null; throw; } finally { _unregisterCalled = true; s_callbackLock.Release(); } WaitThread !.UnregisterWait(this); return(true); }