Task.Run()不会异步运行

时间:2012-12-27 11:19:06

标签: c# asp.net-mvc wcf task

我有一个连接到WCF服务的ASP.NET MVC 3站点。 WCF服务独立于站点,并托管在Windows服务中。 大多数调用是同步的,所以等待WCF做这件事并不是问题。

然而,其中一个(已经实现的)调用需要花费太长时间,因为它本质上不直接输出任何东西,我想在服务上旋转它而忘记它。

所以我改变了我的代码:

public ViewResult StartSlowCalculation(CalculationOptions calculationOptions)
{
  WcfServiceProxy.DoSlowCalculation(calculationOptions);
  ViewBag.Started = true;
  return View();
}

public ViewResult StartSlowCalculation(CalculationOptions calculationOptions)
{
  Task.Run(() =>
  {
    WcfServiceProxy.DoSlowCalculation(calculationOptions);
  });

  ViewBag.Started = true;
  return View();
}

据我所知应该启动一个异步请求,并立即返回。仍然,执行是完全同步的,并且UI被冻结,直到操作结束。

我遗失了哪些明显的东西?


更新

另外,请注意我不希望将服务器实现更改为异步服务器,只是将调用与调用站点上的服务取消同步。

此外,我注意到StartSlowCalculation方法已完成执行,但服务器在服务方法完成执行之前不会返回响应。

WCF服务代理正好:

public void DoSlowCalculation(CalculationOptions calculationOptions)
{
   //some logging code
   Channel.DoSlowCalculation(calculationOptions);
}

因此它完全同步,但这应该无关紧要,因为它应该在一个独立的线程上执行。

2 个答案:

答案 0 :(得分:2)

任务操作可以在调用线程中运行,它取决于taskScheduler的决定。为了帮助TaskScheduler做出有关长时间通话的正确决定,您可以指定任务创建选项TaskCreationOptions.LongRunning

您可以检查任务操作是否在单独的线程中运行:

int launchedByThreadId = Thread.CurrentThread.ManagedThreadId;
int launchedInThreadId = -1;
Task.Run(() =>
  {
    launchedInThreadId = Thread.CurrentThread.ManagedThreadId;
    WcfServiceProxy.DoSlowCalculation(calculationOptions);
  });

// then compare whether thread ids are different
顺便说一句,您使用的是Task.Wait()任何类型的操作吗?它也会阻塞调用线程。

编辑:

您可能会发现以下有趣的帖子Is Task.Factory.StartNew() guaranteed to use another thread than the calling thread?

因此尝试使用Task.Factory.StartNew()并指定取消令牌,即使您不需要它,听起来很奇怪但似乎这保证了任务最终不会在调用线程中运行。纠正我如果我错了。

答案 1 :(得分:0)

我以前做过这个。

最强大的方法是使用异步控制器,或者更好的是一个独立的服务,例如WCF服务。

但根据我的经验,我只需要做一些“简单”的单行任务,例如审计或报告。

  

在该示例中,简单的方法 - 启动任务:

public ViewResult StartSlowCalculation(CalculationOptions calculationOptions)
{
  //Some Synchronous code.

   Task.Factory.StartNew(() =>
  {
    WcfServiceProxy.DoSlowCalculation(calculationOptions);
  });

  ViewBag.Started = true;
  return View();
}

这是一个简单的例子。您可以根据需要启动任意数量的任务,同步它们,在完成时获得通知等等。

有关详细信息,请参阅此链接。

https://msdn.microsoft.com/en-us/library/dd321439(v=vs.110).aspx