private unsafe void EndWrite(IAsyncResult asyncResult) { if (asyncResult == null) { throw new ArgumentNullException("asyncResult"); } if (!_isAsync) { _streamAsyncHelper.EndWrite(asyncResult); return; } PipeStreamAsyncResult afsar = asyncResult as PipeStreamAsyncResult; if (afsar == null || !afsar._isWrite) { throw __Error.GetWrongAsyncResult(); } // Ensure we can't get into any races by doing an interlocked // CompareExchange here. Avoids corrupting memory via freeing the // NativeOverlapped class or GCHandle twice. -- if (1 == Interlocked.CompareExchange(ref afsar._EndXxxCalled, 1, 0)) { throw __Error.GetEndWriteCalledTwice(); } ReadWriteAsyncParams readWriteParams = afsar.AsyncState as ReadWriteAsyncParams; IOCancellationHelper cancellationHelper = null; if (readWriteParams != null) { cancellationHelper = readWriteParams.CancellationHelper; if (cancellationHelper != null) { cancellationHelper.SetOperationCompleted(); } } // Obtain the WaitHandle, but don't use public property in case we // delay initialize the manual reset event in the future. WaitHandle wh = afsar._waitHandle; if (wh != null) { // We must block to ensure that AsyncPSCallback has completed, // and we should close the WaitHandle in here. AsyncPSCallback // and the hand-ported imitation version in COMThreadPool.cpp // are the only places that set this event. using (wh) { wh.WaitOne(); Debug.Assert(afsar._isComplete == true, "PipeStream::EndWrite - AsyncPSCallback didn't set _isComplete to true!"); } } // Free memory & GC handles. NativeOverlapped *overlappedPtr = afsar._overlapped; if (overlappedPtr != null) { _threadPoolBinding.FreeNativeOverlapped(overlappedPtr); } // Now check for any error during the write. if (afsar._errorCode != 0) { if (afsar._errorCode == Interop.mincore.Errors.ERROR_OPERATION_ABORTED) { if (cancellationHelper != null) { cancellationHelper.ThrowIOOperationAborted(); } } WinIOError(afsar._errorCode); } // Number of buffer written is afsar._numBytes. return; }
private unsafe void EndWaitForConnection(IAsyncResult asyncResult) { CheckConnectOperationsServerWithHandle(); if (asyncResult == null) { throw new ArgumentNullException("asyncResult"); } if (!IsAsync) { throw new InvalidOperationException(SR.InvalidOperation_PipeNotAsync); } PipeAsyncResult afsar = asyncResult as PipeAsyncResult; if (afsar == null) { throw __Error.GetWrongAsyncResult(); } // Ensure we can't get into any races by doing an interlocked // CompareExchange here. Avoids corrupting memory via freeing the // NativeOverlapped class or GCHandle twice. -- if (1 == Interlocked.CompareExchange(ref afsar._EndXxxCalled, 1, 0)) { throw __Error.GetEndWaitForConnectionCalledTwice(); } IOCancellationHelper cancellationHelper = afsar.AsyncState as IOCancellationHelper; if (cancellationHelper != null) { cancellationHelper.SetOperationCompleted(); } // Obtain the WaitHandle, but don't use public property in case we // delay initialize the manual reset event in the future. WaitHandle wh = afsar._waitHandle; if (wh != null) { // We must block to ensure that ConnectionIOCallback has completed, // and we should close the WaitHandle in here. AsyncFSCallback // and the hand-ported imitation version in COMThreadPool.cpp // are the only places that set this event. using (wh) { wh.WaitOne(); Debug.Assert(afsar._isComplete == true, "NamedPipeServerStream::EndWaitForConnection - AsyncFSCallback didn't set _isComplete to true!"); } } // We should have freed the overlapped and set it to null either in the Begin // method (if ConnectNamedPipe completed synchronously) or in AsyncWaitForConnectionCallback. // If it is not nulled out, we should not be past the above wait: Debug.Assert(afsar._overlapped == null); // Now check for any error during the read. if (afsar._errorCode != 0) { if (afsar._errorCode == Interop.mincore.Errors.ERROR_OPERATION_ABORTED) { if (cancellationHelper != null) { cancellationHelper.ThrowIOOperationAborted(); } } throw Win32Marshal.GetExceptionForWin32Error(afsar._errorCode); } // Success State = PipeState.Connected; }