我对结合任务并行库和延续有效地使用系统资源感兴趣。
考虑以下场景,它使用GetResponseAsync()
另一个最近的问题中定义的扩展方法。
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);
这种配置存在多个问题,我想知道如何最好地处理它。到目前为止,我确定的主要项目是:
内核的执行
responseTask
通过在异步执行期间不阻塞用户线程来有效地使用资源。但是,由于continuation被定义为Func
lambda,所以执行continuation的线程会阻塞return
在行上,直到后续请求的执行完成。更好的情况是在不阻塞用户线程的情况下提供类似延续的行为。关于取消的行为
responseTask
和finalResultTask
不同。如果在responseTask
执行过程中取消操作,responseTask
将进入状态TaskStatus.Canceled
。但是,如果在执行过程中取消了操作,那么finalResultTask
访问该属性的尝试Result
将导致异常,从而导致任务进入TaskStatus.Failed
状态。- 在失败方面,行为也可能不同。如果在从延续返回
AggregateException
时尝试访问属性时抛出an ,则可能有一个双重包装的真正内部异常(我不确定这里是否发生特殊情况),其中的属性将提供对实际异常应该在第一个任务期间失败。Result
finalResultTask
InnerException
responseTask.Exception
- 在失败方面,行为也可能不同。如果在从延续返回