OwinCommunicationListener 中托管的 Async Web Api 中的 Fire and Forget 方法

Posted

技术标签:

【中文标题】OwinCommunicationListener 中托管的 Async Web Api 中的 Fire and Forget 方法【英文标题】:Fire and Forget method in Async Web Api hosted in OwinCommunicationListener 【发布时间】:2018-03-01 13:20:58 【问题描述】:

最近我可以看到我们正在使用并且运行良好的代码,但我终其一生都无法弄清楚为什么。

我们在通过 OwinCommunicationListener 托管的服务结构集群中托管了一个 Web API。

[HttpPost]
public async Task<HttpResponseMessage> WebApiMethod(RequestObject request)

   string test;
   SomeObject obj;
   ....
   DoSomethingAsync(test, obj);
   return this.ActionContext.CreateResponse(HttpStatusCode.OK, new  Status = "Success" );



private async Task DoSomethingAsync(string param1, SomeObject param2)

    .....
    await SomeOtherAsyncMethod();
    .....

据我了解,这应该是 DoSomethingAsync 的方法完成和请求释放之间的竞争条件,如果稍后提前完成,应该抛出 TaskCancelledException 或其他东西,但它永远不会。

我预计会出现一些错误,因为没有等待 DoSomething 任务,但它每次都完成了它的工作。如果我添加

await Task.Delay(10000);

然后 API 响应几乎是即时的,并且在 10 秒后执行其余代码。到那时不应该释放主机线程,因为原始调用是“即发即弃”(未等待)。

我在这里错过了什么。

【问题讨论】:

我不清楚。为什么您期望从哪里出现异常? 值得一提的是,ASP.Net 中的“一劳永逸”方法几乎总是一个糟糕的主意。您应该使用为处理此类事情而构建的库,例如 Hangfire。或者,由于您似乎在 Azure 中,您可以利用它,而不是 100% 确定调用了哪个功能,可能是 WebJobs? @fildor 我期待一个例外,因为我没有等待 DoSomethingAsync 方法,但它仍然以某种方式每次都设法完成其工作 @DavidG 我严格反对使用上面的代码,但我无法解释它是如何一直工作的 我不明白为什么你会期望它抛出异常?想象一下用 AsyncHandles 实现它。您启动返回 AsyncHandle 的 AsyncOp。你忽略了把手。当开始线程已经超出范围时操作将完成......那又怎样? 【参考方案1】:

没有任何东西可以将请求对象与 DoSomethingAsync 联系起来。但是,即使您将 RequestObj 引用直接传递给 DoSomethingAsync,该方法也将毫无问题地完成,因为在您引用对象时 GC 不会收集您的 RequestObj。此外,一旦异步执行开始,它就会有自己的生命,这意味着回调可能在另一个线程上完成,但请求处理管道已被分派。

【讨论】:

以上是关于OwinCommunicationListener 中托管的 Async Web Api 中的 Fire and Forget 方法的主要内容,如果未能解决你的问题,请参考以下文章