【问题标题】:Task.Run without async or awaitTask.Run 没有异步或等待
【发布时间】:2015-09-28 00:55:42
【问题描述】:

如果我将我正在调用的一些方法(从我的控制器)放入 Task.Run 这究竟是做什么的?我没有使用异步函数,也没有使用 await。

...
FunctionOne();
FunctionTwo();
return View(FunctionThree().Result);
}

private void FunctionOne()
{
        Task.Run(() =>
        {
            ....
        }
}

private void FunctionTwo()
{
        Task.Run(() =>
        {
            ....
        }
}

private Task<MyType> FunctionThree()
{
        return Task.Run(() =>
        {
            ....
        }
}

【问题讨论】:

  • 它将在后台启动任务 1 和 2,然后阻塞并等待任务 3 完成,如果在 UI 线程上运行它可能会死锁。如果/当它完成时,它将返回该任务的结果。任务 1 和 2 可能仍在运行。
  • 为什么会死锁?这个我不是很清楚?您认为这是加快速度的好方法吗?
  • 你认为这是一个好的做法吗?
  • 另外,“这是加快速度的好方法吗?”我不知道,你想做什么?你真的不想在开始任务2之前知道任务1已经完成吗?在开始任务 3 甚至从方法返回之前根本不等待任务 1 或 2?如果你不这样做,那么是的,这看起来是一种解耦独立工作的好方法。

标签: c# task


【解决方案1】:

正如@LasseVKarlsen 解释的那样,此代码尝试并行执行函数一、二和三。 Task.Run 立即将指定的工作排队到线程池中,.Result 将阻塞调用线程,直到其 Task(并且只有它的任务)完成。

这可能是也可能不是一个好的设计。需要考虑的一些事项:

  • 您正在使用线程池中的四个线程来执行此操作。如果这个动作是在重负荷下 - 即。它经常被调用——池中可用线程的数量可能会成为新的瓶颈。
  • 函数一和二的运行时间基本上是无限的,因为没有客户端会等待它们。如果向这些函数添加了太多逻辑,您可能会再次用完池中的线程。
  • 正如@LasseVKarlsen 提到的,这可能会导致deadlock
  • 如果这些是受 CPU 限制的函数,那么并行执行它们可能不会为您带来任何好处。 (但是,不等待 One 和 Two 可能会大量购买 client。)如果下面有 I/O 操作(例如,网络调用、数据库调用、文件系统调用),您可能需要查看改为Using an Asynchronous Controller in ASP.NET MVC
  • 正如@StephenCleary 所说,ASP.NET 不会跟踪您的线程。如果发生回收(例如,当您编辑 web.config 时),它将始终作为请求的一部分完成功能三,但功能一和二可能会被取消。

这些考虑是否表明您的设计发生了变化,这取决于每个功能的作用、它们需要多长时间以及它们对您的业务逻辑的重要性。

【讨论】:

  • 另请注意,每当发生回收时,功能一和二可能会被中止,恕不另行通知。
  • 这真的是我应该关心的事情吗?这是否让您无法使用 Task.Run?
猜你喜欢
  • 2012-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-15
  • 1970-01-01
相关资源
最近更新 更多