应该在不等待ASP.NET MVC网站的情况下执行如下的异步方法。
public async Task DoStaff()
{
// business logic here
}
我们找到了两种解决方案来实现这一目标,并且都在我们的测试平台上运行:
解决方案1 :
public void DoStaffWrapper()
{
DoStaff();
// clean up
}
public ActionResult Caller()
{
DoStaffWrapper();
// return blah blah blah;
}
解决方案2 :
public async Task DoStaffWrapperAsync()
{
await DoStaff();
// clean up
}
public ActionResult Caller()
{
Task.Run(() => DoStaffWrapperAsync());
// return blah blah blah;
}
那么他们之间有什么区别?哪个更好,为什么?有什么好处吗?
答案 0 :(得分:4)
除非您能够精确控制IIS池的生命周期(或者除非您实际上并未在IIS上运行),否则应使用QueueBackgroundWorkItem
启动即发即弃任务。它确保运行时能够跟踪它们,并且不会过早终止该过程。
HostingEnvironment.QueueBackgroundWorkItem(_ => DoStaff());
如果出于某种原因你不想使用这种方法,或者不需要它,那么调用异步方法的两种方法之间有一个重要的区别:
DoStaff()
将在当前线程上同步运行,直到找到await
语句,然后它将控制线程(以及DoStaff
之后能够执行的任何内容此外,mehtod将在ASP.NET的同步上下文中执行,因此如果您在等待内部调用时未使用.ConfigureAwait(false)
,则会遇到麻烦。Task.Run(() => DoStaffWrapperAsync())
将完全异步运行,并且在单独的上下文中(因此您不会遇到上述问题)。 简单来说,请采用以下方法:
public Task DoStaff()
{
Thread.Sleep(1000);
await AnotherMethodAsync();
Thread.Sleep(1000);
}
如果您拨打DoStaff
,则通话将被阻止一秒钟。如果您拨打Task.Run(() => DoStaff())
,呼叫将立即返回。但是如果在第一个await
之前没有大量的工作,那么你将跳到一个新的线程,没有实际的收获。