简体   繁体   English

ASP.NET WebApi中的async / await在后台

[英]async/await in background in ASP.NET WebApi

Let's suppose i have the following async method that needs fairly long time until completing its work: 假设我有以下异步方法,需要相当长的时间才能完成其工作:

void async Task LongWork()
{
    await LONGWORK() // ... long work 
}

Now, in an web api, i would like to run that work in a background (ie, i want to return the Http Request after starting that LongWork() but before its completion: 现在,在web api中,我想在后台运行该工作(即,我想在启动LongWork()之后但在完成之前返回Http请求:

I can think of three approaches to achieve this: 我可以想到实现这个目标的三种方法:

1) public async Task<string> WebApi()
   {
       ... // do another work

       await Task.Factory.StartNew(() => LongWork());

       return "ok";
   }
2) public async Task<string> WebApi()
   {
       ... // do another work

       await Task.Factory.StartNew(async () => await LongWork());

       return "ok";
   }

3) public async Task<string> WebApi()
   {
       ... // do another work

       Task.Factory.StartNew(async () => await LongWork());

       return "ok";
   }

Q1: What's the difference between approach #1 and #2? Q1:方法#1和#2之间有什么区别?

Q2: What is the right way to, in the ASP.NET world, run a method (in this example, LongWork() containing some async/await pairs in a background thread? In particular, in #3, there's no "await" before Task.Factory.StartNew(async () => await LongWork()). Is it fine? Q2:在ASP.NET世界中,运行方法(在此示例中,LongWork()在后台线程中包含一些异步/等待对的正确方法是什么?特别是在#3中,没有“等待”在Task.Factory.StartNew之前(async()=> await LongWork())。没问题吗?

Thanks! 谢谢!

Q1: What's the difference between approach #1 and #2? Q1:方法#1和#2之间有什么区别?

#1 has less overhead. #1的开销较小。 That is the only difference. 这是唯一的区别。

Q2: What is the right way to, in the ASP.NET world, run a method (in this example, LongWork() containing some async/await pairs in a background thread? Q2:在ASP.NET世界中,运行方法(在此示例中,LongWork()在后台线程中包含一些异步/等待对的正确方法是什么?

None of the options you provided. 您没有提供任何选项。 For one thing, they all use Task.Factory.StartNew without specifying a TaskScheduler , which is dangerous (as I describe on my blog). 首先,他们都使用Task.Factory.StartNew而没有指定TaskScheduler ,这很危险 (正如我在博客中描述的那样)。 They should use Task.Run instead. 他们应该使用Task.Run However, even if you use Task.Run , you will run into a more serious underlying problem. 但是,即使您使用Task.Run ,您也会遇到更严重的潜在问题。

The underlying problem is this: the HTTP protocol is centered around each request having exactly one matching response. 潜在的问题是:HTTP协议以每个请求为中心,只有一个匹配的响应。 When an HTTP server (such as ASP.NET) knows that there are no outstanding requests, it will make assumptions like "it's safe to recycle the worker process". 当HTTP服务器(例如ASP.NET)知道没有未完成的请求时,它会做出“回收工作进程是安全的”这样的假设。

I describe this problem in more detail on my blog . 我在博客上更详细地描述了这个问题 Also in that blog post is a type BackgroundTaskManager that registers background tasks with the ASP.NET runtime and (correctly) executes them via Task.Run . 此博客文章中还有一个BackgroundTaskManager类型,它使用ASP.NET运行时注册后台任务,并通过Task.Run (正确)执行它们。 You should only use BackgroundTaskManager if you read the blog post and understand and accept that this is still dangerous and unsafe. 如果您阅读博客文章并理解并接受这仍然是危险且不安全的,您应该只使用BackgroundTaskManager

A far better (read: more reliable) solution is to first write out a representation of the work to be done to persistent storage (eg, an Azure queue) and have an independent backend process (eg, an Azure worker role) that processes requests from the queue. 更好(读取:更可靠)的解决方案是首先写出要对持久存储(例如,Azure队列)执行的工作的表示,并且具有处理请求的独立后端进程(例如,Azure工作者角色)。从队列中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM