private static unsafe void AsyncPSCallback(uint errorCode, uint numBytes, NativeOverlapped *pOverlapped) { PipeStreamAsyncResult asyncResult = (PipeStreamAsyncResult)Overlapped.Unpack(pOverlapped).AsyncResult; asyncResult._numBytes = (int)numBytes; if (!asyncResult._isWrite && (((errorCode == 0x6d) || (errorCode == 0xe9)) || (errorCode == 0xe8))) { errorCode = 0; numBytes = 0; } if (errorCode == 0xea) { errorCode = 0; asyncResult._isMessageComplete = false; } else { asyncResult._isMessageComplete = true; } asyncResult._errorCode = (int)errorCode; asyncResult._completedSynchronously = false; asyncResult._isComplete = true; ManualResetEvent event2 = asyncResult._waitHandle; if ((event2 != null) && !event2.Set()) { System.IO.__Error.WinIOError(); } AsyncCallback callback = asyncResult._userCallback; if (callback != null) { callback(asyncResult); } }
private unsafe PipeStreamAsyncResult BeginWriteCore(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { PipeStreamAsyncResult ar = new PipeStreamAsyncResult { _userCallback = callback, _userStateObject = state, _isWrite = true, _handle = this.m_handle }; if (buffer.Length == 0) { ar.CallUserCallback(); return(ar); } ManualResetEvent event2 = new ManualResetEvent(false); ar._waitHandle = event2; NativeOverlapped *overlapped = new Overlapped(0, 0, IntPtr.Zero, ar).Pack(IOCallback, buffer); ar._overlapped = overlapped; int hr = 0; if ((this.WriteFileNative(this.m_handle, buffer, offset, count, overlapped, out hr) == -1) && (hr != 0x3e5)) { if (overlapped != null) { Overlapped.Free(overlapped); } this.WinIOError(hr); } return(ar); }
internal void CallUserCallback() { if (_userCallback != null) { _completedSynchronously = false; ThreadPool.QueueUserWorkItem(s => { PipeStreamAsyncResult ar = (PipeStreamAsyncResult)s; ar._isComplete = true; if (ar._waitHandle != null) { ar._waitHandle.Set(); } ar._userCallback(ar); }, this); } else { _isComplete = true; if (_waitHandle != null) { _waitHandle.Set(); } } }
private IAsyncResult BeginRead(AsyncCallback callback, Object state) { ReadWriteAsyncParams readWriteParams = state as ReadWriteAsyncParams; Debug.Assert(readWriteParams != null); byte[] buffer = readWriteParams.Buffer; int offset = readWriteParams.Offset; int count = readWriteParams.Count; if (buffer == null) { throw new ArgumentNullException("buffer", SR.ArgumentNull_Buffer); } if (offset < 0) { throw new ArgumentOutOfRangeException("offset", SR.ArgumentOutOfRange_NeedNonNegNum); } if (count < 0) { throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum); } if (buffer.Length - offset < count) { throw new ArgumentException(SR.Argument_InvalidOffLen); } if (!CanRead) { throw __Error.GetReadNotSupported(); } CheckReadOperations(); if (!_isAsync) { // special case when this is called for sync broken pipes because otherwise Stream's // Begin/EndRead hang. Reads return 0 bytes in this case so we can call the user's // callback immediately if (_state == PipeState.Broken) { PipeStreamAsyncResult asyncResult = new PipeStreamAsyncResult(); asyncResult._handle = _handle; asyncResult._userCallback = callback; asyncResult._userStateObject = state; asyncResult._isWrite = false; asyncResult.CallUserCallback(); return(asyncResult); } else { return(_streamAsyncHelper.BeginRead(buffer, offset, count, callback, state)); } } else { return(BeginReadCore(buffer, offset, count, callback, state)); } }
public override unsafe int EndRead(IAsyncResult asyncResult) { if (asyncResult == null) { throw new ArgumentNullException("asyncResult"); } if (!this.m_isAsync) { return(base.EndRead(asyncResult)); } PipeStreamAsyncResult result = asyncResult as PipeStreamAsyncResult; if ((result == null) || result._isWrite) { System.IO.__Error.WrongAsyncResult(); } if (1 == Interlocked.CompareExchange(ref result._EndXxxCalled, 1, 0)) { System.IO.__Error.EndReadCalledTwice(); } WaitHandle handle = result._waitHandle; if (handle != null) { try { handle.WaitOne(); } finally { handle.Close(); } } NativeOverlapped *nativeOverlappedPtr = result._overlapped; if (nativeOverlappedPtr != null) { Overlapped.Free(nativeOverlappedPtr); } if (result._errorCode != 0) { this.WinIOError(result._errorCode); } this.m_isMessageComplete = (this.m_state == PipeState.Broken) || result._isMessageComplete; return(result._numBytes); }
public override unsafe void EndWrite(IAsyncResult asyncResult) { if (asyncResult == null) { throw new ArgumentNullException("asyncResult"); } if (!this.m_isAsync) { base.EndWrite(asyncResult); } else { PipeStreamAsyncResult result = asyncResult as PipeStreamAsyncResult; if ((result == null) || !result._isWrite) { System.IO.__Error.WrongAsyncResult(); } if (1 == Interlocked.CompareExchange(ref result._EndXxxCalled, 1, 0)) { System.IO.__Error.EndWriteCalledTwice(); } WaitHandle handle = result._waitHandle; if (handle != null) { try { handle.WaitOne(); } finally { handle.Close(); } } NativeOverlapped *nativeOverlappedPtr = result._overlapped; if (nativeOverlappedPtr != null) { Overlapped.Free(nativeOverlappedPtr); } if (result._errorCode != 0) { this.WinIOError(result._errorCode); } } }
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { if (buffer == null) { throw new ArgumentNullException("buffer", System.SR.GetString("ArgumentNull_Buffer")); } if (offset < 0) { throw new ArgumentOutOfRangeException("offset", System.SR.GetString("ArgumentOutOfRange_NeedNonNegNum")); } if (count < 0) { throw new ArgumentOutOfRangeException("count", System.SR.GetString("ArgumentOutOfRange_NeedNonNegNum")); } if ((buffer.Length - offset) < count) { throw new ArgumentException(System.SR.GetString("Argument_InvalidOffLen")); } if (!this.CanRead) { System.IO.__Error.ReadNotSupported(); } this.CheckReadOperations(); if (this.m_isAsync) { return(this.BeginReadCore(buffer, offset, count, callback, state)); } if (this.m_state == PipeState.Broken) { PipeStreamAsyncResult result = new PipeStreamAsyncResult { _handle = this.m_handle, _userCallback = callback, _userStateObject = state, _isWrite = false }; result.CallUserCallback(); return(result); } return(base.BeginRead(buffer, offset, count, callback, state)); }
private unsafe PipeStreamAsyncResult BeginReadCore(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { PipeStreamAsyncResult ar = new PipeStreamAsyncResult { _handle = this.m_handle, _userCallback = callback, _userStateObject = state, _isWrite = false }; if (buffer.Length == 0) { ar.CallUserCallback(); return(ar); } ManualResetEvent event2 = new ManualResetEvent(false); ar._waitHandle = event2; NativeOverlapped *overlapped = new Overlapped(0, 0, IntPtr.Zero, ar).Pack(IOCallback, buffer); ar._overlapped = overlapped; int hr = 0; if (this.ReadFileNative(this.m_handle, buffer, offset, count, overlapped, out hr) == -1) { if ((hr == 0x6d) || (hr == 0xe9)) { this.State = PipeState.Broken; overlapped->InternalLow = IntPtr.Zero; ar.CallUserCallback(); return(ar); } if (hr != 0x3e5) { System.IO.__Error.WinIOError(hr, string.Empty); } } return(ar); }
unsafe private PipeStreamAsyncResult BeginReadCore(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) { Debug.Assert(_handle != null, "_handle is null"); Debug.Assert(!_handle.IsClosed, "_handle is closed"); Debug.Assert(CanRead, "can't read"); Debug.Assert(buffer != null, "buffer == null"); Debug.Assert(_isAsync, "BeginReadCore doesn't work on synchronous file streams!"); Debug.Assert(offset >= 0, "offset is negative"); Debug.Assert(count >= 0, "count is negative"); // Create and store async stream class library specific data in the async result PipeStreamAsyncResult asyncResult = new PipeStreamAsyncResult(); asyncResult._handle = _handle; asyncResult._userCallback = callback; asyncResult._userStateObject = state; asyncResult._isWrite = false; // handle zero-length buffers separately; fixed keyword ReadFileNative doesn't like // 0-length buffers. Call user callback and we're done if (buffer.Length == 0) { asyncResult.CallUserCallback(); } else { // For Synchronous IO, I could go with either a userCallback and using // the managed Monitor class, or I could create a handle and wait on it. ManualResetEvent waitHandle = new ManualResetEvent(false); asyncResult._waitHandle = waitHandle; NativeOverlapped *intOverlapped = _threadPoolBinding.AllocateNativeOverlapped(s_IOCallback, asyncResult, buffer); asyncResult._overlapped = intOverlapped; // Queue an async ReadFile operation and pass in a packed overlapped int errorCode = 0; int r = ReadFileNative(_handle, buffer, offset, count, intOverlapped, out errorCode); // ReadFile, the OS version, will return 0 on failure, but this ReadFileNative wrapper // returns -1. This will return the following: // - On error, r==-1. // - On async requests that are still pending, r==-1 w/ hr==ERROR_IO_PENDING // - On async requests that completed sequentially, r==0 // // You will NEVER RELIABLY be able to get the number of buffer read back from this call // when using overlapped structures! You must not pass in a non-null lpNumBytesRead to // ReadFile when using overlapped structures! This is by design NT behavior. if (r == -1) { // One side has closed its handle or server disconnected. Set the state to Broken // and do some cleanup work if (errorCode == Interop.mincore.Errors.ERROR_BROKEN_PIPE || errorCode == Interop.mincore.Errors.ERROR_PIPE_NOT_CONNECTED) { State = PipeState.Broken; // Clear the overlapped status bit for this special case. Failure to do so looks // like we are freeing a pending overlapped. intOverlapped->InternalLow = IntPtr.Zero; // EndRead will free the Overlapped struct asyncResult.CallUserCallback(); } else if (errorCode != Interop.mincore.Errors.ERROR_IO_PENDING) { throw Win32Marshal.GetExceptionForWin32Error(errorCode); } } ReadWriteAsyncParams readWriteParams = state as ReadWriteAsyncParams; if (readWriteParams != null) { if (readWriteParams.CancellationHelper != null) { readWriteParams.CancellationHelper.AllowCancellation(_handle, intOverlapped); } } } return(asyncResult); }
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 PipeStreamAsyncResult BeginReadCore(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { PipeStreamAsyncResult ar = new PipeStreamAsyncResult { _handle = this.m_handle, _userCallback = callback, _userStateObject = state, _isWrite = false }; if (buffer.Length == 0) { ar.CallUserCallback(); return ar; } ManualResetEvent event2 = new ManualResetEvent(false); ar._waitHandle = event2; NativeOverlapped* overlapped = new Overlapped(0, 0, IntPtr.Zero, ar).Pack(IOCallback, buffer); ar._overlapped = overlapped; int hr = 0; if (this.ReadFileNative(this.m_handle, buffer, offset, count, overlapped, out hr) == -1) { if ((hr == 0x6d) || (hr == 0xe9)) { this.State = PipeState.Broken; overlapped->InternalLow = IntPtr.Zero; ar.CallUserCallback(); return ar; } if (hr != 0x3e5) { System.IO.__Error.WinIOError(hr, string.Empty); } } return ar; }
private IAsyncResult BeginRead(AsyncCallback callback, Object state) { ReadWriteAsyncParams readWriteParams = state as ReadWriteAsyncParams; Debug.Assert(readWriteParams != null); byte[] buffer = readWriteParams.Buffer; int offset = readWriteParams.Offset; int count = readWriteParams.Count; if (buffer == null) { throw new ArgumentNullException("buffer", SR.ArgumentNull_Buffer); } if (offset < 0) { throw new ArgumentOutOfRangeException("offset", SR.ArgumentOutOfRange_NeedNonNegNum); } if (count < 0) { throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum); } if (buffer.Length - offset < count) { throw new ArgumentException(SR.Argument_InvalidOffLen); } if (!CanRead) { throw __Error.GetReadNotSupported(); } CheckReadOperations(); if (!_isAsync) { // special case when this is called for sync broken pipes because otherwise Stream's // Begin/EndRead hang. Reads return 0 bytes in this case so we can call the user's // callback immediately if (_state == PipeState.Broken) { PipeStreamAsyncResult asyncResult = new PipeStreamAsyncResult(); asyncResult._handle = _handle; asyncResult._userCallback = callback; asyncResult._userStateObject = state; asyncResult._isWrite = false; asyncResult.CallUserCallback(); return asyncResult; } else { return _streamAsyncHelper.BeginRead(buffer, offset, count, callback, state); } } else { return BeginReadCore(buffer, offset, count, callback, state); } }
unsafe private PipeStreamAsyncResult BeginWriteCore(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) { Debug.Assert(_handle != null, "_handle is null"); Debug.Assert(!_handle.IsClosed, "_handle is closed"); Debug.Assert(CanWrite, "can't write"); Debug.Assert(buffer != null, "buffer == null"); Debug.Assert(_isAsync, "BeginWriteCore doesn't work on synchronous file streams!"); Debug.Assert(offset >= 0, "offset is negative"); Debug.Assert(count >= 0, "count is negative"); // Create and store async stream class library specific data in the async result PipeStreamAsyncResult asyncResult = new PipeStreamAsyncResult(); asyncResult._userCallback = callback; asyncResult._userStateObject = state; asyncResult._isWrite = true; asyncResult._handle = _handle; // fixed doesn't work well with zero length arrays. Set the zero-byte flag in case // caller needs to do any cleanup if (buffer.Length == 0) { //intOverlapped->InternalLow = IntPtr.Zero; // EndRead will free the Overlapped struct asyncResult.CallUserCallback(); } else { // For Synchronous IO, I could go with either a userCallback and using the managed // Monitor class, or I could create a handle and wait on it. ManualResetEvent waitHandle = new ManualResetEvent(false); asyncResult._waitHandle = waitHandle; NativeOverlapped *intOverlapped = _threadPoolBinding.AllocateNativeOverlapped(s_IOCallback, asyncResult, buffer); asyncResult._overlapped = intOverlapped; int errorCode = 0; // Queue an async WriteFile operation and pass in a packed overlapped int r = WriteFileNative(_handle, buffer, offset, count, intOverlapped, out errorCode); // WriteFile, the OS version, will return 0 on failure, but this WriteFileNative // wrapper returns -1. This will return the following: // - On error, r==-1. // - On async requests that are still pending, r==-1 w/ hr==ERROR_IO_PENDING // - On async requests that completed sequentially, r==0 // // You will NEVER RELIABLY be able to get the number of buffer written back from this // call when using overlapped structures! You must not pass in a non-null // lpNumBytesWritten to WriteFile when using overlapped structures! This is by design // NT behavior. if (r == -1 && errorCode != Interop.mincore.Errors.ERROR_IO_PENDING) { // Clean up if (intOverlapped != null) { _threadPoolBinding.FreeNativeOverlapped(intOverlapped); } WinIOError(errorCode); } ReadWriteAsyncParams readWriteParams = state as ReadWriteAsyncParams; if (readWriteParams != null) { if (readWriteParams.CancellationHelper != null) { readWriteParams.CancellationHelper.AllowCancellation(_handle, intOverlapped); } } } return(asyncResult); }
unsafe private PipeStreamAsyncResult BeginWriteCore(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) { Debug.Assert(_handle != null, "_handle is null"); Debug.Assert(!_handle.IsClosed, "_handle is closed"); Debug.Assert(CanWrite, "can't write"); Debug.Assert(buffer != null, "buffer == null"); Debug.Assert(_isAsync, "BeginWriteCore doesn't work on synchronous file streams!"); Debug.Assert(offset >= 0, "offset is negative"); Debug.Assert(count >= 0, "count is negative"); // Create and store async stream class library specific data in the async result PipeStreamAsyncResult asyncResult = new PipeStreamAsyncResult(); asyncResult._userCallback = callback; asyncResult._userStateObject = state; asyncResult._isWrite = true; asyncResult._handle = _handle; // fixed doesn't work well with zero length arrays. Set the zero-byte flag in case // caller needs to do any cleanup if (buffer.Length == 0) { //intOverlapped->InternalLow = IntPtr.Zero; // EndRead will free the Overlapped struct asyncResult.CallUserCallback(); } else { // For Synchronous IO, I could go with either a userCallback and using the managed // Monitor class, or I could create a handle and wait on it. ManualResetEvent waitHandle = new ManualResetEvent(false); asyncResult._waitHandle = waitHandle; // Create a managed overlapped class; set the file offsets later Overlapped overlapped = new Overlapped(); overlapped.OffsetLow = 0; overlapped.OffsetHigh = 0; overlapped.AsyncResult = asyncResult; // Pack the Overlapped class, and store it in the async result NativeOverlapped* intOverlapped = overlapped.Pack(s_IOCallback, buffer); asyncResult._overlapped = intOverlapped; int errorCode = 0; // Queue an async WriteFile operation and pass in a packed overlapped int r = WriteFileNative(_handle, buffer, offset, count, intOverlapped, out errorCode); // WriteFile, the OS version, will return 0 on failure, but this WriteFileNative // wrapper returns -1. This will return the following: // - On error, r==-1. // - On async requests that are still pending, r==-1 w/ hr==ERROR_IO_PENDING // - On async requests that completed sequentially, r==0 // // You will NEVER RELIABLY be able to get the number of buffer written back from this // call when using overlapped structures! You must not pass in a non-null // lpNumBytesWritten to WriteFile when using overlapped structures! This is by design // NT behavior. if (r == -1 && errorCode != Interop.ERROR_IO_PENDING) { // Clean up if (intOverlapped != null) Overlapped.Free(intOverlapped); WinIOError(errorCode); } ReadWriteAsyncParams readWriteParams = state as ReadWriteAsyncParams; if (readWriteParams != null) { if (readWriteParams.CancellationHelper != null) { readWriteParams.CancellationHelper.AllowCancellation(_handle, intOverlapped); } } } return asyncResult; }
unsafe private PipeStreamAsyncResult BeginReadCore(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) { Debug.Assert(_handle != null, "_handle is null"); Debug.Assert(!_handle.IsClosed, "_handle is closed"); Debug.Assert(CanRead, "can't read"); Debug.Assert(buffer != null, "buffer == null"); Debug.Assert(_isAsync, "BeginReadCore doesn't work on synchronous file streams!"); Debug.Assert(offset >= 0, "offset is negative"); Debug.Assert(count >= 0, "count is negative"); // Create and store async stream class library specific data in the async result PipeStreamAsyncResult asyncResult = new PipeStreamAsyncResult(); asyncResult._handle = _handle; asyncResult._userCallback = callback; asyncResult._userStateObject = state; asyncResult._isWrite = false; // handle zero-length buffers separately; fixed keyword ReadFileNative doesn't like // 0-length buffers. Call user callback and we're done if (buffer.Length == 0) { asyncResult.CallUserCallback(); } else { // For Synchronous IO, I could go with either a userCallback and using // the managed Monitor class, or I could create a handle and wait on it. ManualResetEvent waitHandle = new ManualResetEvent(false); asyncResult._waitHandle = waitHandle; // Create a managed overlapped class; set the file offsets later Overlapped overlapped = new Overlapped(); overlapped.OffsetLow = 0; overlapped.OffsetHigh = 0; overlapped.AsyncResult = asyncResult; // Pack the Overlapped class, and store it in the async result NativeOverlapped* intOverlapped; intOverlapped = overlapped.Pack(s_IOCallback, buffer); asyncResult._overlapped = intOverlapped; // Queue an async ReadFile operation and pass in a packed overlapped int errorCode = 0; int r = ReadFileNative(_handle, buffer, offset, count, intOverlapped, out errorCode); // ReadFile, the OS version, will return 0 on failure, but this ReadFileNative wrapper // returns -1. This will return the following: // - On error, r==-1. // - On async requests that are still pending, r==-1 w/ hr==ERROR_IO_PENDING // - On async requests that completed sequentially, r==0 // // You will NEVER RELIABLY be able to get the number of buffer read back from this call // when using overlapped structures! You must not pass in a non-null lpNumBytesRead to // ReadFile when using overlapped structures! This is by design NT behavior. if (r == -1) { // One side has closed its handle or server disconnected. Set the state to Broken // and do some cleanup work if (errorCode == Interop.ERROR_BROKEN_PIPE || errorCode == Interop.ERROR_PIPE_NOT_CONNECTED) { State = PipeState.Broken; // Clear the overlapped status bit for this special case. Failure to do so looks // like we are freeing a pending overlapped. intOverlapped->InternalLow = IntPtr.Zero; // EndRead will free the Overlapped struct asyncResult.CallUserCallback(); } else if (errorCode != Interop.ERROR_IO_PENDING) { throw Win32Marshal.GetExceptionForWin32Error(errorCode); } } ReadWriteAsyncParams readWriteParams = state as ReadWriteAsyncParams; if (readWriteParams != null) { if (readWriteParams.CancellationHelper != null) { readWriteParams.CancellationHelper.AllowCancellation(_handle, intOverlapped); } } } return asyncResult; }
private unsafe PipeStreamAsyncResult BeginWriteCore(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { PipeStreamAsyncResult ar = new PipeStreamAsyncResult { _userCallback = callback, _userStateObject = state, _isWrite = true, _handle = this.m_handle }; if (buffer.Length == 0) { ar.CallUserCallback(); return ar; } ManualResetEvent event2 = new ManualResetEvent(false); ar._waitHandle = event2; NativeOverlapped* overlapped = new Overlapped(0, 0, IntPtr.Zero, ar).Pack(IOCallback, buffer); ar._overlapped = overlapped; int hr = 0; if ((this.WriteFileNative(this.m_handle, buffer, offset, count, overlapped, out hr) == -1) && (hr != 0x3e5)) { if (overlapped != null) { Overlapped.Free(overlapped); } this.WinIOError(hr); } return ar; }
private unsafe int EndRead(IAsyncResult asyncResult) { // There are 3 significantly different IAsyncResults we'll accept // here. One is from Stream::BeginRead. The other two are variations // on our PipeStreamAsyncResult. One is from BeginReadCore, // while the other is from the BeginRead buffering wrapper. if (asyncResult == null) { throw new ArgumentNullException("asyncResult"); } if (!_isAsync) { return(_streamAsyncHelper.EndRead(asyncResult)); } 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.GetEndReadCalledTwice(); } ReadWriteAsyncParams readWriteParams = asyncResult.AsyncState as ReadWriteAsyncParams; IOCancellationHelper cancellationHelper = null; if (readWriteParams != null) { cancellationHelper = readWriteParams.CancellationHelper; if (cancellationHelper != null) { readWriteParams.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, "FileStream::EndRead - 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 read. if (afsar._errorCode != 0) { if (afsar._errorCode == Interop.mincore.Errors.ERROR_OPERATION_ABORTED) { if (cancellationHelper != null) { cancellationHelper.ThrowIOOperationAborted(); } } WinIOError(afsar._errorCode); } // set message complete to true if the pipe is broken as well; need this to signal to readers // to stop reading _isMessageComplete = _state == PipeState.Broken || afsar._isMessageComplete; return(afsar._numBytes); }
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { if (buffer == null) { throw new ArgumentNullException("buffer", System.SR.GetString("ArgumentNull_Buffer")); } if (offset < 0) { throw new ArgumentOutOfRangeException("offset", System.SR.GetString("ArgumentOutOfRange_NeedNonNegNum")); } if (count < 0) { throw new ArgumentOutOfRangeException("count", System.SR.GetString("ArgumentOutOfRange_NeedNonNegNum")); } if ((buffer.Length - offset) < count) { throw new ArgumentException(System.SR.GetString("Argument_InvalidOffLen")); } if (!this.CanRead) { System.IO.__Error.ReadNotSupported(); } this.CheckReadOperations(); if (this.m_isAsync) { return this.BeginReadCore(buffer, offset, count, callback, state); } if (this.m_state == PipeState.Broken) { PipeStreamAsyncResult result = new PipeStreamAsyncResult { _handle = this.m_handle, _userCallback = callback, _userStateObject = state, _isWrite = false }; result.CallUserCallback(); return result; } return base.BeginRead(buffer, offset, count, callback, state); }
unsafe private static void AsyncPSCallback(uint errorCode, uint numBytes, NativeOverlapped *pOverlapped) { // Extract async result from overlapped PipeStreamAsyncResult asyncResult = (PipeStreamAsyncResult)ThreadPoolBoundHandle.GetNativeOverlappedState(pOverlapped); asyncResult._numBytes = (int)numBytes; // Allow async read to finish if (!asyncResult._isWrite) { if (errorCode == Interop.mincore.Errors.ERROR_BROKEN_PIPE || errorCode == Interop.mincore.Errors.ERROR_PIPE_NOT_CONNECTED || errorCode == Interop.mincore.Errors.ERROR_NO_DATA) { errorCode = 0; numBytes = 0; } } // For message type buffer. if (errorCode == Interop.mincore.Errors.ERROR_MORE_DATA) { errorCode = 0; asyncResult._isMessageComplete = false; } else { asyncResult._isMessageComplete = true; } asyncResult._errorCode = (int)errorCode; // Call the user-provided callback. It can and often should // call EndRead or EndWrite. There's no reason to use an async // delegate here - we're already on a threadpool thread. // IAsyncResult's completedSynchronously property must return // false here, saying the user callback was called on another thread. asyncResult._completedSynchronously = false; asyncResult._isComplete = true; // The OS does not signal this event. We must do it ourselves. ManualResetEvent wh = asyncResult._waitHandle; if (wh != null) { Debug.Assert(!wh.GetSafeWaitHandle().IsClosed, "ManualResetEvent already closed!"); bool r = wh.Set(); Debug.Assert(r, "ManualResetEvent::Set failed!"); if (!r) { throw Win32Marshal.GetExceptionForLastWin32Error(); } } AsyncCallback callback = asyncResult._userCallback; if (callback != null) { callback(asyncResult); } }
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) { if (buffer == null) { throw new ArgumentNullException("buffer", SR.GetString(SR.ArgumentNull_Buffer)); } if (offset < 0) { throw new ArgumentOutOfRangeException("offset", SR.GetString(SR.ArgumentOutOfRange_NeedNonNegNum)); } if (count < 0) { throw new ArgumentOutOfRangeException("count", SR.GetString(SR.ArgumentOutOfRange_NeedNonNegNum)); } if (buffer.Length - offset < count) { throw new ArgumentException(SR.GetString(SR.Argument_InvalidOffLen)); } if (!CanRead) { __Error.ReadNotSupported(); } CheckReadOperations(); if (!m_isAsync) { // special case when this is called for sync broken pipes because otherwise Stream's // Begin/EndRead hang. Reads return 0 bytes in this case so we can call the user's // callback immediately if (m_state == PipeState.Broken) { PipeStreamAsyncResult asyncResult = new PipeStreamAsyncResult(); asyncResult._handle = m_handle; asyncResult._userCallback = callback; asyncResult._userStateObject = state; asyncResult._isWrite = false; asyncResult.CallUserCallback(); return asyncResult; } else { return base.BeginRead(buffer, offset, count, callback, state); } } else { return BeginReadCore(buffer, offset, count, callback, state); } }