// Begin an asynchronous read of the request entity body.  To read the entire entity, invoke
    // repeatedly until total bytes read is equal to Request.ContentLength or EndRead indicates
    // that zero bytes were read.  If Request.ContentLength is zero and the request is chunked,
    // then invoke repeatedly until EndRead indicates that zero bytes were read.
    //
    // If an error occurs and the client is no longer connected, an HttpException will be thrown.
    //
    // This implements Stream.BeginRead, and as such, should throw
    // exceptions as described on MSDN when errors occur.
    public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) {
        // Do as Stream does.
        if (buffer == null)
            throw new ArgumentNullException("buffer");
        if (offset < 0)
            throw new ArgumentOutOfRangeException("offset");
        if (count < 0)
            throw new ArgumentOutOfRangeException("count");
        if (buffer.Length - offset < count)
            throw new ArgumentException(SR.GetString(SR.InvalidOffsetOrCount, "offset", "count"));
        if (_ecb == IntPtr.Zero)
            throw new InvalidOperationException();

        ReadAsyncResult ar = new ReadAsyncResult(callback, state, buffer, offset, count, updatePerfCounter: false);

        if (count == 0) {
            ar.Complete(0, HResults.S_OK, IntPtr.Zero, synchronous: true);
            return ar;
        }

        // we only allow one async operation at a time
        if (Interlocked.CompareExchange(ref _asyncResultBase, ar, null) != null)
            throw new InvalidOperationException(SR.GetString(SR.Async_operation_pending));
        
        // initiate async operation here
        if (_asyncCompletionCallback == null) {
            _asyncCompletionCallback = new AsyncCompletionCallback(OnAsyncCompletion);
        }
        _rootedThis = GCHandle.Alloc(this); // root for duration of async operation

        int hresult;
        try {
            ar.MarkCallToBeginMethodStarted();
            hresult = UnsafeNativeMethods.EcbReadClientAsync(_ecb,
                                                             count,
                                                             _asyncCompletionCallback);
        }
        finally {
            ar.MarkCallToBeginMethodCompleted();
        }

        if (hresult < 0) {
            _rootedThis.Free();
            _asyncResultBase = null;
            // treat every error as if the client disconnected
            IncrementRequestsDisconnected();
            throw new HttpException(SR.GetString(SR.ClientDisconnected), hresult);
        }
        else {
            return ar;
        }
    }
예제 #2
0
 internal static extern int EcbReadClientAsync(IntPtr pECB, int dwBytesToRead, AsyncCompletionCallback pfnCallback);
    // Begin an asynchronous flush of the response.  To support this, the worker request buffers
    // the status, headers, and resonse body until an asynchronous flush operation is initiated.
    public override IAsyncResult BeginFlush(AsyncCallback callback, Object state) {
        if (_ecb == IntPtr.Zero) {
            throw new InvalidOperationException();
        }
        
        FlushAsyncResult ar = new FlushAsyncResult(callback, state);
        
        // we only allow one async operation at a time
        if (Interlocked.CompareExchange(ref _asyncResultBase, ar, null) != null)
            throw new InvalidOperationException(SR.GetString(SR.Async_operation_pending));

        // initiate async operation here
        if (_asyncCompletionCallback == null) {
            _asyncCompletionCallback = new AsyncCompletionCallback(OnAsyncCompletion);
        }

        try {
            ar.MarkCallToBeginMethodStarted();
            FlushResponse(finalFlush: false);
        }
        finally {
            ar.MarkCallToBeginMethodCompleted();
        }

        return ar;
    }