运行 方法在 Action 中的单独线程上

Run method on a separate thread inside Action

假设我有一个如下所示的操作,我想 return 尽快查看并继续在后台线程中做一些工作。

public async Task<ActionResult> Index()
{
    Debug.WriteLine("Inside Index");

    var newCustomer = new Customer
    {
        Name = "Ibrahim"
    };

    Task.Run(() => SaveCustomer(newCustomer));

    Debug.WriteLine("Exiting Index");

    return View();
}

private async Task SaveCustomer(Customer NewCustomer)
{
    Debug.WriteLine("Started Saving Customer");

    await Task.Delay(2000);

    Debug.WriteLine("Completed Saving Customer");
}

我确实得到了预期的输出:

Inside Index
Exiting Index
Started Saving Customer
Completed Saving Customer

但令我困扰的是,我收到一条警告,我的 Index 操作将 运行 同步,而我应该放一个 await 但视图是 return 在 SaveCustomer 完成并且目的失败后编辑。

我怎么做错了?任何建议表示赞赏。

您的 Index 根本没有使用任何异步功能。为什么标记为async?你一定是误会了什么,不确定是什么。删除 async Task 规范。

您收到该编译器警告是因为您的 Index() 方法中没有任何异步内容。您的 Task.Run(() => SaveCustomer(newCustomer)); 行表示即发即弃(非等待任务)——这与 异步 代码非常不同。 Index() 是完全同步的,同时创建一个 "side Task" 以在将来某个时间执行。正如提到的另一个答案 - 你也可以从你的方法中删除异步标记 - 它不是异步的。

But what bothers me is that I get a warning that my Index action will run synchronously

How am I doing this wrong?

不要自上而下强制异步。相反,从最低级别 的自然异步操作开始(例如,EF6 数据库访问),并允许异步从最低级别的代码向上增长。

另外,在 ASP.NET,你应该强烈避免 Task.Run

应用这两个原则会产生如下 Index 方法:

public async Task<ActionResult> Index()
{
  Debug.WriteLine("Inside Index");

  var newCustomer = new Customer
  {
    Name = "Ibrahim"
  };

  await SaveCustomer(newCustomer);

  Debug.WriteLine("Exiting Index");

  return View();
}

but then the view is returned after SaveCustomer is completed and the purpose is defeated.

完全没有。异步ASP.NET代码的目的是不是到return早到客户端。 asyncawait 不更改 HTTP 协议。 await 服务器端让步给线程池,而不是客户端。

如果你需要到return早(大多数人不需要 - 他们只是认为他们“需要”到),那么你应该使用 one of the established patterns for returning early(正如我在我的博客中描述的那样)。请注意,唯一正确(即完全可靠)的解决方案需要设置一个具有独立后台进程的可靠队列。