I'm interested in efficiently using system resources in conjunction with the Task Parallel Library and continuations.
Consider the following scenario which uses the GetResponseAsync() extension method defined in another recent question.
WebRequest request = HttpWebRequest.Create(uri);
Task<WebResponse> responseTask = request.GetResponseAsync(cancellationToken);
Func<Task<WebResponse>, WebResponse> continuation =
task =>
{
WebRequest followup = HttpWebRequest.Create(uri2);
return followup.GetResponseAsync(cancellationToken).Result;
};
Task<WebResponse> finalResultTask = responseTask.ContinueWith(continuation, cancellationToken);
There are multiple problems with this configuration, and I'm wondering how this can best be handled. The major items I've identified so far are:
The execution of the core of
responseTaskefficiently uses resources by not blocking a user thread during the asynchronous execution. However, since the continuation is defined as aFunclambda, the thread executing the continuation will block on thereturnline until the execution of the follow-up request is complete. A better situation would provide continuation-like behavior while not blocking a user thread.The behavior of
responseTaskandfinalResultTaskdiffer in regards to cancellation. If operation is cancelled whileresponseTaskis executing,responseTaskwill enter the stateTaskStatus.Canceled. However, if the operation is canceled whilefinalResultTaskis executing, the attempt to access theResultproperty will result in an exception, causing the task to enter theTaskStatus.Failedstate.- The behavior may also differ in regards to failure. If an
AggregateExceptionis thrown when attempting to access theResultproperty when returning from the continuation, thenfinalResultTaskmay have a doubly-wrapped true inner exception (I'm not sure if a special case occurs here), where theInnerExceptionproperty ofresponseTask.Exceptionwould provide direct access to the actual exception should it fail during the first task.
- The behavior may also differ in regards to failure. If an
request.GetResponseAsyncinstead offollowup.GetResponseAsyncinside the continuation function, and calling the continuation function ascontinuationdespite declaring it asresult). - Douglas