【问题标题】:DelegatingHandler hangs when returning Task<HttpResponseMessage>DelegatingHandler 在返回 Task<HttpResponseMessage> 时挂起
【发布时间】:2018-12-21 17:56:27
【问题描述】:

这是我演示问题的非常简单的课程:

public class SimpleHandler : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            return new Task<HttpResponseMessage>(
                        () => new HttpResponseMessage(HttpStatusCode.Unauthorized));

            //return base.SendAsync(request, cancellationToken);
        }
    }

预期的行为是 401 响应。如果我调试它,执行到达返回语句并在我按 F5 时继续执行,但 http 请求永远不会返回,并且 http 客户端最终会等到超时。

我真的很困惑,因为我正在做编译器告诉我的事情:返回 Task&lt;HttpResponseMessage&gt;。对 base.SendAsync 的调用工作得很好。我在这里错过了什么?

编辑:

好的,所以我发现了

return Task.FromResult(new HttpResponseMessage(HttpStatusCode.Unauthorized));

按预期工作。但是,我想了解为什么上述方法失败了?在这两种情况下,我都在创建 Task&lt;HttpResponseMessage&gt; 为什么我只在第二种情况下获得预期的行为?

【问题讨论】:

    标签: c# asp.net asp.net-web-api2 task-parallel-library


    【解决方案1】:

    有很大的不同。使用构造函数创建的任务表示尚未运行的任务,因此还没有结果集。在您的情况下,无需完成任何工作,因此无需创建和运行任务。否则You should use Task.Run instead of a constructor

    并且由于您仅在示例中创建了任务,并且没有调用Start(),因此它将具有Created 状态并且永远不会自行完成,因为它不会启动。因此,您的进程会挂起,因为系统将在管道的下方等待任务完成。

    第二个任务是使用FromResult 创建的,表示一个任务已经完成,并具有设定值作为结果。

    检查两个 Task 的 Status 属性并注意差异。 (Created 与 RanToCompletion)

    由于您没有实际工作要做,您应该坚持使用FromResult

    【讨论】:

    • Task.Run 在这里似乎不合适。你为什么要为此委托给线程池? Task.FromResult 似乎更正确。
    • @PeterBons 我的困惑源于仅依赖返回类型。我怎么知道我应该返回一个已经开始的任务?如果调用代码/框架要自己启动任务怎么办?您的回答是有道理的,但前提是假设应该开始任务。我只是在任何地方都没有看到这种假设的迹象。
    【解决方案2】:

    您可以使用静态 Task.FromResult 方法,该方法用于创建一个包含特定值的任务:

    Task.FromResult<HttpResponseMessage>(new HttpResponseMessage(HttpStatusCode.Unauthorized));
    

    【讨论】:

      猜你喜欢
      • 2015-04-22
      • 1970-01-01
      • 2016-12-02
      • 2012-12-13
      • 2014-09-09
      • 1970-01-01
      • 2020-08-10
      • 2016-07-02
      • 1970-01-01
      相关资源
      最近更新 更多