DelegatingHandler 在返回 Task<HttpResponseMessage> 时挂起
DelegatingHandler hangs when returning Task<HttpResponseMessage>
这是我非常简单的 class 演示问题:
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 响应。如果我调试它,执行到达 return 语句并在我按下 F5 时继续,但 http 请求永远不会 returns 并且 http 客户端最终会等待超时。
我真的很困惑,因为我正在做编译器告诉我的事情:return a Task<HttpResponseMessage>
。对 base.SendAsync 的调用工作得很好。我在这里错过了什么?
编辑:
好的,所以我发现
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.Unauthorized));
按预期工作。但是,我想了解为什么上述方法失败了?在这两种情况下,我都在创建一个 Task<HttpResponseMessage>
为什么我只在第二种情况下得到预期的行为?
您可以使用静态 Task.FromResult 方法来创建一个 Task,它是一个特定值的包装器:
Task.FromResult<HttpResponseMessage>(new HttpResponseMessage(HttpStatusCode.Unauthorized));
区别很大。使用构造函数创建的任务表示尚未 运行 的任务,因此还没有结果集。在您的情况下,无需完成任何工作,因此无需创建和 运行 任务。否则 You should use Task.Run instead of a constructor。
并且由于您只在示例中创建了任务,而没有调用 Start()
,它将具有 Created
状态并且永远不会自行完成,因为它不会启动。因此您的进程挂起,因为在管道的更下方,系统将等待任务完成。
第二个Task,使用FromResult
创建,代表一个Task已经完成,结果为设定值。
检查两个任务的 de Status
属性 并注意差异。 (创建与 RanToCompletion)
由于您没有实际工作要做,因此您应该坚持使用 FromResult
。
这是我非常简单的 class 演示问题:
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 响应。如果我调试它,执行到达 return 语句并在我按下 F5 时继续,但 http 请求永远不会 returns 并且 http 客户端最终会等待超时。
我真的很困惑,因为我正在做编译器告诉我的事情:return a Task<HttpResponseMessage>
。对 base.SendAsync 的调用工作得很好。我在这里错过了什么?
编辑:
好的,所以我发现
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.Unauthorized));
按预期工作。但是,我想了解为什么上述方法失败了?在这两种情况下,我都在创建一个 Task<HttpResponseMessage>
为什么我只在第二种情况下得到预期的行为?
您可以使用静态 Task.FromResult 方法来创建一个 Task,它是一个特定值的包装器:
Task.FromResult<HttpResponseMessage>(new HttpResponseMessage(HttpStatusCode.Unauthorized));
区别很大。使用构造函数创建的任务表示尚未 运行 的任务,因此还没有结果集。在您的情况下,无需完成任何工作,因此无需创建和 运行 任务。否则 You should use Task.Run instead of a constructor。
并且由于您只在示例中创建了任务,而没有调用 Start()
,它将具有 Created
状态并且永远不会自行完成,因为它不会启动。因此您的进程挂起,因为在管道的更下方,系统将等待任务完成。
第二个Task,使用FromResult
创建,代表一个Task已经完成,结果为设定值。
检查两个任务的 de Status
属性 并注意差异。 (创建与 RanToCompletion)
由于您没有实际工作要做,因此您应该坚持使用 FromResult
。