Return 使用异步等待查看
Return to View with Async Await
我有一个进程想 运行 在后台运行。这是通过单击操作 link.
来执行的
要调用的操作:
public async Task<ActionResult> ProcessRec()
{
await Task.Run(() => waitTimer());
return RedirectToAction("Index", "Home");
}
public void waitTimer()
{
Thread.Sleep(10000);
}
然而,这会等待整整 10 秒,然后才会将我重定向到我的 "Index, Home" 操作。我对 Await/Async 很陌生,所以我知道我在这里解释错了。当 waitTimer 在后台执行时,如何让应用程序 return 执行此操作?谢谢!!
正如您所发现的,await
会阻止响应在完成之前返回给用户。通常,您只需将后台工作放在另一个线程上并通过不等待将其设置为 "fire and forget",但是在 ASP.NET 中,IIS 将关闭未使用的 AppDomains,并且 Task.Run
不会通知IIS,您的后台线程 "is using the AppDomain" 因此您的后台线程可以在 AppDomain 关闭期间以 Thread.Abort()
终止。
如果您使用的是 .NET 4.5.2 或更新版本,您可以通过 QueueBackgroundWorkItem
告诉 IIS 您有一个后台工作程序,您需要保持活动状态。你会像这样使用它
public ActionResult ProcessRec()
{
HostingEnvironment.QueueBackgroundWorkItem(waitTimer);
return RedirectToAction("Index", "Home");
}
public void waitTimer(CancellationToken token)
{
Thread.Sleep(10000);
}
//You also could do
public async Task waitTimer2(CancellationToken token)
{
await Task.Delay(10000);
}
现在这并不能保证 IIS 不会关闭您的应用程序域,但它确实会让它知道您正在处理某事,并在它确实尝试关闭它时要求更多时间(您起床默认情况下,开始关机后 90 秒完成所有排队的后台项目。
有关详细信息,请阅读 this MSDN blog 介绍。
我正在考虑将消息发送到队列(如 azure storage/service 总线队列),以便您可以立即得到回复。
然后创建另一个服务来出列和处理消息(执行您的长 运行 任务)
此外,如果这是一个 Azure 网站(Web 应用程序),您可以使用 Web 作业!
希望对您有所帮助。
This however waits for the full 10 seconds before redirecting me to my "Index, Home" action.
对,那是因为 await
异步等待操作完成。它会将线程返回到池中,直到操作完成。
How do I get the application to return to this action, while the waitTimer is executing in the background?
Task.Run 是危险的,因为它不使用 IIS which can lead to problems. Instead, you can use BackgroundTaskManager or HangFire 注册工作,后者注册它的执行 ASP.NET:
BackgroundTaskManager.Run(() => { waitTimer() };
return RedirectToAction("Index", "Home");
public async Task<IActionResult> Index()
{
return await Task.Run(() =>
{
return View();
});
}
我有一个进程想 运行 在后台运行。这是通过单击操作 link.
来执行的要调用的操作:
public async Task<ActionResult> ProcessRec()
{
await Task.Run(() => waitTimer());
return RedirectToAction("Index", "Home");
}
public void waitTimer()
{
Thread.Sleep(10000);
}
然而,这会等待整整 10 秒,然后才会将我重定向到我的 "Index, Home" 操作。我对 Await/Async 很陌生,所以我知道我在这里解释错了。当 waitTimer 在后台执行时,如何让应用程序 return 执行此操作?谢谢!!
await
会阻止响应在完成之前返回给用户。通常,您只需将后台工作放在另一个线程上并通过不等待将其设置为 "fire and forget",但是在 ASP.NET 中,IIS 将关闭未使用的 AppDomains,并且 Task.Run
不会通知IIS,您的后台线程 "is using the AppDomain" 因此您的后台线程可以在 AppDomain 关闭期间以 Thread.Abort()
终止。
如果您使用的是 .NET 4.5.2 或更新版本,您可以通过 QueueBackgroundWorkItem
告诉 IIS 您有一个后台工作程序,您需要保持活动状态。你会像这样使用它
public ActionResult ProcessRec()
{
HostingEnvironment.QueueBackgroundWorkItem(waitTimer);
return RedirectToAction("Index", "Home");
}
public void waitTimer(CancellationToken token)
{
Thread.Sleep(10000);
}
//You also could do
public async Task waitTimer2(CancellationToken token)
{
await Task.Delay(10000);
}
现在这并不能保证 IIS 不会关闭您的应用程序域,但它确实会让它知道您正在处理某事,并在它确实尝试关闭它时要求更多时间(您起床默认情况下,开始关机后 90 秒完成所有排队的后台项目。
有关详细信息,请阅读 this MSDN blog 介绍。
我正在考虑将消息发送到队列(如 azure storage/service 总线队列),以便您可以立即得到回复。
然后创建另一个服务来出列和处理消息(执行您的长 运行 任务)
此外,如果这是一个 Azure 网站(Web 应用程序),您可以使用 Web 作业!
希望对您有所帮助。
This however waits for the full 10 seconds before redirecting me to my "Index, Home" action.
对,那是因为 await
异步等待操作完成。它会将线程返回到池中,直到操作完成。
How do I get the application to return to this action, while the waitTimer is executing in the background?
Task.Run 是危险的,因为它不使用 IIS which can lead to problems. Instead, you can use BackgroundTaskManager or HangFire 注册工作,后者注册它的执行 ASP.NET:
BackgroundTaskManager.Run(() => { waitTimer() };
return RedirectToAction("Index", "Home");
public async Task<IActionResult> Index()
{
return await Task.Run(() =>
{
return View();
});
}