在Action

时间:2015-09-05 19:38:47

标签: asp.net-mvc multithreading asynchronous async-await task-parallel-library

假设我有一个类似下面的Action,我想尽快返回View并继续在后台线程中做一些工作。

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,但在SaveCustomer完成后返回视图目的被打败了。

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

3 个答案:

答案 0 :(得分:2)

  

但令我困扰的是,我收到警告,我的Index动作将同步运行

     

我怎么做错了?

不要从上到下强制异步。相反,从最低级别的自然异步操作开始(例如,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();
}
  

但是在SaveCustomer完成后返回视图并且目的被取消。

完全没有。异步ASP.NET代码的目的是 而不是 以尽早返回到客户端。 asyncawait不会更改HTTP协议。服务器端的await产生线程池,而不是客户端。

如果您需要提前退货(并且大多数人不会 - 他们只是认为他们需要&#34;需要&#34;)应该使用one of the established patterns for returning early(正如我在博客中描述的那样)。请注意,唯一正确(即完全可靠)的解决方案需要使用独立的后台进程建立可靠的队列。

答案 1 :(得分:1)

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

答案 2 :(得分:1)

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