// 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 (_context == 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 bool async = true; bool completedSynchronously; int hresult = IIS.MgdExplicitFlush(_context, async, out completedSynchronously); if (hresult < 0) { _asyncResultBase = null; // treat every error as if the client disconnected IncrementRequestsDisconnected(); throw new HttpException(SR.GetString(SR.ClientDisconnected), hresult); } else if (completedSynchronously) { _asyncResultBase = null; ar.Complete(0, HResults.S_OK, IntPtr.Zero, synchronous: true); return ar; } else { return ar; } }
// 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; }
// Sends the currently buffered response to the client. If the underlying HttpWorkerRequest // supports asynchronous flush and this method is called from an asynchronous module event // or asynchronous handler, then the send will be performed asynchronously. Otherwise the // implementation resorts to a synchronous flush. The HttpResponse.SupportsAsyncFlush property // returns the value of HttpWorkerRequest.SupportsAsyncFlush. Asynchronous flush is supported // for IIS 6.0 and higher. public IAsyncResult BeginFlush(AsyncCallback callback, Object state) { if (_completed) throw new HttpException(SR.GetString(SR.Cannot_flush_completed_response)); // perform async flush if it is supported if (_wr != null && _wr.SupportsAsyncFlush && !_context.IsInCancellablePeriod) { Flush(false, true); return _wr.BeginFlush(callback, state); } // perform a [....] flush since async is not supported FlushAsyncResult ar = new FlushAsyncResult(callback, state); try { Flush(false); } catch(Exception e) { ar.SetError(e); } ar.Complete(0, HResults.S_OK, IntPtr.Zero, synchronous: true); return ar; }