第三方物流可持续发展中的有效资源利用

本文关键字:有效 资源 发展中 第三方 | 更新日期: 2023-09-27 18:21:35

我感兴趣的是将系统资源与任务并行库和continuations结合使用。

考虑以下场景,该场景使用最近另一个问题中定义的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);

这种配置存在多个问题,我想知道如何最好地处理这些问题。到目前为止,我确定的主要项目有:

  1. CCD_ 2的核心的执行通过在异步执行期间不阻塞用户线程而有效地使用资源。但是,由于continuation被定义为Func lambda,执行continuation的线程将在return行阻塞,直到后续请求的执行完成。更好的情况是在不阻塞用户线程的情况下提供类似延续的行为。

  2. CCD_ 5和CCD_ 6的行为在抵消方面不同。如果在执行responseTask时取消操作,则responseTask将进入状态TaskStatus.Canceled。但是,如果在执行finalResultTask时取消操作,则尝试访问Result属性将导致异常,导致任务进入TaskStatus.Failed状态。

    • 行为也可能因失败而有所不同。如果在从延续返回时尝试访问Result属性时抛出AggregateException,则finalResultTask可能具有双重包装的真正内部异常(我不确定这里是否发生了特殊情况),如果responseTask.ExceptionInnerException属性在第一个任务期间失败,它将提供对实际异常的直接访问

第三方物流可持续发展中的有效资源利用

我怀疑如果使用Unwrap扩展方法,您的两个问题都会得到解决。您的目标是返回一个新任务作为您的延续功能的结果;然而,由于continuation本身是作为任务执行的,这将导致额外级别的嵌套(任务返回任务)。因此,您需要使用Unwrap来消除这种嵌套,这将为您提供一个绑定到内部任务结果的代理任务。

WebRequest request = HttpWebRequest.Create(uri);
Task<WebResponse> responseTask = request.GetResponseAsync(cancellationToken);
Func<Task<WebResponse>, Task<WebResponse> continuation =
    task =>
    {
        WebRequest followup = HttpWebRequest.Create(uri2);
        return followup.GetResponseAsync(cancellationToken);
    };
Task<Task<WebResponse>> finalResultTask = responseTask.ContinueWith(continuation);
Task<WebResponse> proxyTask = finalResultTask.Unwrap();

快速优化:由于您的延续函数除了通过responseTask0生成一个新任务外,几乎没有其他功能,因此您可以通过将其指定为ExecuteSynchronously:来减少其执行开销

Task<Task<WebResponse>> finalResultTask = responseTask.ContinueWith(continuation, 
    TaskContinuationOptions.ExecuteSynchronously);

编辑:根据Servy的建议,您也应该将CancellationToken传递给您的延续函数:

Task<Task<WebResponse>> finalResultTask = responseTask.ContinueWith(continuation, 
    cancellationToken,
    TaskContinuationOptions.ExecuteSynchronously,
    TaskScheduler.Current);