// This is the method that the underlying, free-threaded // asynchronous behavior will invoke. This will happen on // an arbitrary thread. private void OnAsyncCompletionMethod(object operationState) { AsyncData data = operationState as AsyncData; AsyncOperation asyncOp = data.Operation; AsyncOperationCompletedEventArgs args = new AsyncOperationCompletedEventArgs(data); // In this case, don't allow cancellation, as the method // is about to raise the completed event. lock (_userStateToLifetime.SyncRoot) { if (!_userStateToLifetime.Contains(data.UserData)) { asyncOp = null; } else { _userStateToLifetime.Remove(asyncOp.UserSuppliedState); } } // The asyncOp object is responsible for marshaling // the call. if (asyncOp != null) { asyncOp.PostOperationCompleted(_onCompletedDelegate, args); } // Note that after the call to OperationCompleted, // asyncOp is no longer usable, and any attempt to use it // will cause an exception to be thrown. }
private MemoryStream CopyResponseToMemory(AsyncData data, Stream responseStream, long contentLength) { if (responseStream == null) { return(null); } // read the stream into memory. That's the only way to satisfy the "main work // on the other thread requirement MemoryStream memStream = new MemoryStream(); const int size = 4096; var bytes = new byte[size]; int numBytes; double current = 0; long bytesWritten = 0; while ((numBytes = responseStream.Read(bytes, 0, size)) > 0) { memStream.Write(bytes, 0, numBytes); if (data == null || data.Delegate == null) { continue; } bytesWritten += numBytes; if (contentLength > size) { current = bytesWritten * 100d / contentLength; } // see if we are still in the list... // Multiple threads will access the task dictionary, // so it must be locked to serialize access. if (CheckIfOperationIsCancelled(data.UserData)) { throw new ArgumentException("Operation was cancelled"); } var args = new AsyncOperationProgressEventArgs( contentLength, bytesWritten, (int)current, data.UriToUse, data.HttpVerb, data.UserData); data.Operation.Post(data.Delegate, args); } memStream.Seek(0, SeekOrigin.Begin); return(memStream); }
/// <summary> /// handles the response stream /// copies it into the memory stream, or parses it into a feed. /// </summary> /// <param name="data"></param> /// <param name="responseStream"></param> /// <param name="contentLength"></param> /// <returns></returns> protected override void HandleResponseStream(AsyncData data, Stream responseStream, long contentLength) { if (data.ParseFeed) { data.Feed = CreateAndParseFeed(responseStream, data.UriToUse); data.DataStream = null; } else { base.HandleResponseStream(data, responseStream, contentLength); } }
/// <summary> /// handles the response stream /// copies it into the memory stream, or parses it into a feed. /// </summary> /// <param name="data"></param> /// <param name="responseStream"></param> /// <param name="contentLength"></param> /// <returns></returns> protected virtual void HandleResponseStream(AsyncData data, Stream responseStream, long contentLength, IService service) { data.DataStream = CopyResponseToMemory(data, responseStream, contentLength); IAsyncEntryData entryData = data as IAsyncEntryData; Service serviceImpl = service as Service; if (entryData != null && service != null) { entryData.Entry = serviceImpl.CreateAndParseEntry(data.DataStream, data.UriToUse); } }
internal bool SendProgressData(AsyncData data, AsyncOperationProgressEventArgs args) { // In this case, don't allow cancellation, as the method // is about to raise the completed event. bool ret = !CheckIfOperationIsCancelled(data.UserData); if (ret) { data.Operation.Post(data.Delegate, args); } return(ret); }
/// <summary> /// constructor. takes the async data blob /// </summary> /// <param name="data">async data to constructor</param> internal AsyncOperationCompletedEventArgs(AsyncData data) : base(data.Exception, false, data.UserData) { _feedObject = data.Feed; _stream = data.DataStream; IAsyncEntryData entryData = data as IAsyncEntryData; if (entryData != null) { _entryObject = entryData.Entry; } }
/// <summary> /// this method cancels the corresponding async operation. /// It sends still a completed event, but that event will then /// have the cancel property set to true /// </summary> /// <param name="userData">your identifier for the operation to be cancelled</param> public void CancelAsync(object userData) { lock (_userStateToLifetime.SyncRoot) { object obj = _userStateToLifetime[userData]; if (obj != null) { _userStateToLifetime.Remove(userData); AsyncOperation asyncOp = obj as AsyncOperation; // The asyncOp object is responsible for // marshaling the call to the proper // thread or context. AsyncData data = new AsyncData(null, userData, _onProgressReportDelegate); AsyncOperationCompletedEventArgs args = new AsyncOperationCompletedEventArgs(data, true); asyncOp.PostOperationCompleted(_onCompletedDelegate, args); } } }
internal AsyncOperationCompletedEventArgs(AsyncData data, bool cancelled) : base(data.Exception, cancelled, data.UserData) { }
/// <summary> /// handles the response stream /// copies it into the memory stream, or parses it into a feed. /// </summary> /// <param name="data"></param> /// <param name="responseStream"></param> /// <param name="contentLength"></param> /// <returns></returns> protected virtual void HandleResponseStream(AsyncData data, Stream responseStream, long contentLength) { HandleResponseStream(data, responseStream, contentLength, null); }