private ProgressReportingTask <TResult, TProgress> GetAsynchronousResponseWithProgress <TResult, TProgress>(AsyncResults taskCompletionSource, CancellationToken cancellationToken) { ProgressReportingTask <TResult, TProgress> progressReportingTask = new ProgressReportingTask <TResult, TProgress>( progress => { object obj; while (taskCompletionSource.TryTake(out obj, (int)TimeSpan.FromMinutes(2).TotalMilliseconds, cancellationToken)) { progress.MakeProgress((TProgress)obj); if (obj is TProgress) { progress.MakeProgress((TProgress)obj); } else if (obj is TResult) { return((TResult)obj); } else { throw new ArgumentException("Cannot process result type of " + taskCompletionSource.GetConsumingEnumerable(cancellationToken).First().GetType()); } } throw new AbandonedMutexException("We did not receive of reply from the server after 2 minutes for transaction " + taskCompletionSource.Id); }, cancellationToken, TaskCreationOptions.None); progressReportingTask.Start(BackgroundTaskScheduler.OnBackground()); Task tt = progressReportingTask; tt.OnCancelled( canceled => { Trace.WriteLine("Got some more cancels"); }, UITaskScheduler.InvokeAsync()); // bug here - not being called on cancel return(progressReportingTask); }
/// <summary> /// Wires up the given callbacks with the internal implementation of network callbacks. Note this should be called only once /// per asyncResult, otherwise data will be lost. /// </summary> /// <typeparam name="TProgress">The type of data contract that is returned to show progress.</typeparam> /// <typeparam name="TResult">The type of data contract returned when the operation completes or fails.</typeparam> /// <param name="userCallback">The callback to wire up.</param> /// <param name="asyncResults">The <see cref="AsyncResults"/> associated with the current call.</param> protected void SetupCallback <TProgress, TResult>(Callback <TProgress, TResult> userCallback, AsyncResults asyncResults) { ProgressReportingTask <TResult, TProgress> responseWithProgress = GetAsynchronousResponseWithProgress <TResult, TProgress>(asyncResults, userCallback.CancellationToken); ((Task)responseWithProgress).OnCancelled( canceled => { CancelTransaction(asyncResults.Id); userCallback.OnCanceled(); }, userCallback.CanceledScheduler); // bug here - not being called on cancel Task <TResult> result = responseWithProgress.OnProgress( progressData => userCallback.OnProgress(progressData), userCallback.ProgressScheduler); result.Pipeline( finished => { if (finished.Result is IFaulted && ((IFaulted)finished.Result).IsFaulted) { throw new AggregateException(((IFaulted)finished.Result).Message); } userCallback.OnCompleted(finished.Result); }, userCallback.CompletedScheduler) .OnError( exception => userCallback.OnError(exception) , userCallback.ErrorScheduler); }