c# - 在 ASP.NET MVC 中无需等待即可启动异步任务的两种方法之间的区别

标签 c# asp.net asp.net-mvc asynchronous async-await

<分区>

像下面这样的异步方法应该在 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;    
}

那么它们有什么区别呢?哪个更好,为什么?有什么好处吗?

最佳答案

除非您可以精确控制 IIS 池的生命周期(或者除非您实际上没有在 IIS 上运行),否则您应该使用 QueueBackgroundWorkItem 启动您的即发即弃任务。它确保运行时能够跟踪它们,并且不会过早地终止进程。

HostingEnvironment.QueueBackgroundWorkItem(_ => DoStaff());

如果由于某种原因你不想使用这个方法,或者不需要它,那么调用异步方法的两种方式之间有一个重要的区别:

  • DoStaff()将在当前线程上同步运行,直到 await找到语句,然后它将放弃对线程的控制(并且您在 DoStaff 之后拥有的任何内容都将能够执行。此外,该方法将在 ASP.NET 的同步上下文中执行,因此如果您无论何时在其中等待调用,我们都不会使用 .ConfigureAwait(false)
  • Task.Run(() => DoStaffWrapperAsync())将完全异步运行,并在单独的上下文中运行(因此您不会遇到上述问题)。

简单来说,采取以下方法:

public Task DoStaff()
{
    Thread.Sleep(1000);

    await AnotherMethodAsync();

    Thread.Sleep(1000);
}

如果您调用 DoStaff ,调用将阻塞一秒钟。如果您调用 Task.Run(() => DoStaff()) ,调用将立即返回。但是如果在第一个 await 之前没有大量的工作,那么您将跳到一个新线程而没有任何实际 yield 。

关于c# - 在 ASP.NET MVC 中无需等待即可启动异步任务的两种方法之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44403824/

相关文章:

c# - 此 View 不允许使用 EditItem

c# - 泛型中的排序列表

asp.net - 即使通过 ssl 在 ViewState 中存储信用卡和定价信息是否安全?

asp.net - MVC ViewModel 错误 - 没有为此对象定义无参数构造函数

c# - 当 ContractFor 在不同的程序集上时,C# 的代码契约(Contract)不起作用

c# - 为 Windows Phone 库解决方案运行单元测试

c# - 复杂的 SQL 查询数据绑定(bind)到 DataGrid

asp.net-mvc - 表单例份验证和子域

c# - Entity Framework 数据注释对 DDD 和关注点分离有害吗?

c# - ASP.NET MVC (C#) 中的经典 ASP