private WaitForMultipleObjects ( uint count, |
||
count | uint | |
handles | ||
waitAll | [ | |
milliseconds | uint | |
return | uint |
public unsafe static void OverlappedOperation(IntPtr ioHandle, IntPtr eventHandle, int eventTimeout, IntPtr closeEventHandle, bool overlapResult, NativeOverlapped *overlapped, out uint bytesTransferred) { bool closed = false; if (!overlapResult) { int win32Error = Marshal.GetLastWin32Error(); if (win32Error != NativeMethods.ERROR_IO_PENDING) { throw new IOException("Operation failed early.", new Win32Exception()); } IntPtr *handles = stackalloc IntPtr[2]; handles[0] = eventHandle; handles[1] = closeEventHandle; uint timeout = eventTimeout < 0 ? ~(uint)0 : (uint)eventTimeout; uint waitResult = NativeMethods.WaitForMultipleObjects(2, handles, false, timeout); switch (waitResult) { case NativeMethods.WAIT_OBJECT_0: break; case NativeMethods.WAIT_OBJECT_1: closed = true; goto default; default: CancelIo(ioHandle); break; } } if (!NativeMethods.GetOverlappedResult(ioHandle, overlapped, out bytesTransferred, true)) { int win32Error = Marshal.GetLastWin32Error(); if (win32Error != NativeMethods.ERROR_HANDLE_EOF) { if (closed) { throw new IOException("Connection closed."); } if (win32Error == NativeMethods.ERROR_OPERATION_ABORTED) { throw new TimeoutException("Operation timed out."); } throw new IOException("Operation failed after some time.", new Win32Exception()); } bytesTransferred = 0; } }
// usbser.sys does not register an interface, at least on Windows 7 and earlier. (Other serial drivers don't suffer from this flaw.) // In any case, to detect connections and disconnections, let's watch the SERIALCOMM registry key. static unsafe void SerialWatcherThread() { var notifyEvent = NativeMethods.CreateAutoResetEventOrThrow(); try { IntPtr handle; if (0 == NativeMethods.RegOpenKeyEx(new IntPtr(unchecked ((int)NativeMethods.HKEY_LOCAL_MACHINE)), @"HARDWARE\DEVICEMAP\SERIALCOMM", 0, NativeMethods.KEY_NOTIFY, out handle)) { try { var handles = stackalloc IntPtr[2]; handles[0] = _serialWatcherShutdownEvent; handles[1] = notifyEvent; while (true) { if (0 != NativeMethods.RegNotifyChangeKeyValue(handle, false, NativeMethods.REG_NOTIFY_CHANGE_LAST_SET, notifyEvent, true)) { break; } switch (NativeMethods.WaitForMultipleObjects(2, handles, false, uint.MaxValue)) { case NativeMethods.WAIT_OBJECT_0: default: return; case NativeMethods.WAIT_OBJECT_1: HidSharpDiagnostics.Trace("Received a serial change event."); DeviceListDidChange(ref _serNotifyObject); break; } } } finally { NativeMethods.RegCloseKey(handle); } } } finally { NativeMethods.CloseHandle(notifyEvent); } }
public override unsafe BleEvent ReadEvent() { HandleAcquireIfOpenOrFail(); try { while (true) { IntPtr *handles = stackalloc IntPtr[2]; handles[0] = _watchEventHandle; handles[1] = _closeEventHandle; uint waitResult = NativeMethods.WaitForMultipleObjects(2, handles, false, NativeMethods.WaitForMultipleObjectsGetTimeout(ReadTimeout)); switch (waitResult) { case NativeMethods.WAIT_OBJECT_0: break; case NativeMethods.WAIT_OBJECT_1: throw CommonException.CreateClosedException(); default: throw new TimeoutException(); } lock (_watchSync) { // We *may* have multiple threads calling ReadEvent(). Another thread may have read the event. // FIXME: If so, the timeout is not going to operate correctly here. if (_watchEvents.Count == 0) { NativeMethods.ResetEvent(_watchEventHandle); continue; } var @event = _watchEvents.Dequeue(); if (_watchEvents.Count == 0) { NativeMethods.ResetEvent(_watchEventHandle); } return(@event); } } } finally { HandleRelease(); } }