static unsafe void FinishOverlappedAsynchronously(SafeObjectHandle handle, PinnedStruct <OVERLAPPED> overlapped, ManualResetEvent finishedEvent, TaskCompletionSource <int> completionSource, CancellationToken cancellationToken) { var alreadyFinished = false; var lockObject = new object(); WaitOrTimerCallback callback = (state, timedOut) => { var overlappedState = (OverlappedState)state; lock (lockObject) { if (alreadyFinished) { return; } overlappedState.Unregister(); if (overlappedState.IsCancellation || cancellationToken.IsCancellationRequested) { CancelIoEx(handle, (OVERLAPPED *)overlapped.Pointer); completionSource.SetCanceled(); } else { int bytesReturned; var overlappedResult = GetOverlappedResult(handle, (OVERLAPPED *)overlapped.Pointer, out bytesReturned, false); overlapped.Dispose(); finishedEvent.Dispose(); if (overlappedResult) { completionSource.SetResult(bytesReturned); } else { SetFromLastWin32Exception(completionSource); } } alreadyFinished = true; } }; lock (lockObject) { var finishedState = new OverlappedState(false); var cancelledState = new OverlappedState(true); var finishedWait = ThreadPool.RegisterWaitForSingleObject(finishedEvent, callback, finishedState, -1, true); cancelledState.OtherRegistration = finishedWait; if (cancellationToken != CancellationToken.None) { var cancelledWait = ThreadPool.RegisterWaitForSingleObject(cancellationToken.WaitHandle, callback, cancelledState, -1, true); finishedState.OtherRegistration = cancelledWait; } } }
static unsafe bool FinishOverlappedSynchronously(SafeObjectHandle handle, CancellationToken cancellationToken, PinnedStruct <OVERLAPPED> overlapped, TaskCompletionSource <int> completionSource, bool nativeMethodResult) { if (!nativeMethodResult) { var error = Marshal.GetLastWin32Error(); if (error != ErrorIoPending) { if (cancellationToken.IsCancellationRequested) { completionSource.SetCanceled(); } else { SetFromLastWin32Exception(completionSource); } return(true); } // Async IO in progress return(false); } int pBytesReturned; GetOverlappedResult(handle, (OVERLAPPED *)overlapped.Pointer, out pBytesReturned, false); if (cancellationToken.IsCancellationRequested) { completionSource.SetCanceled(); } else { completionSource.SetResult(pBytesReturned); } return(true); }