Task.Run vs ThreadPool.QueueUserWorkItem

Ste*_*ano 22 .net asynchronous

我不是一个主题专家,我试图更多地了解.NET中可用的异步世界.Task.Run和ThreadPool.QueueUserWorkItem都允许在池线程上调度工作,但有什么区别,或者,如果您愿意,两者的优缺点是什么?以下是我的专业人士名单.不确定它是完整的还是正确的.

ThreadPool.QueueUserWorkItem专业人士:

  • 通过论证的可能性

Task.Run专业人士:

  • 提供CancellationToken的可能性
  • 等待任务完成的可能性
  • 将值返回给调用代码的可能性

Sco*_*ain 25

ThreadPool.QueueUserWorkItem只是在.NET 1.1中引入相同工作的旧实现(在.NET 1.1中Task.Run引入).

Microsoft试图避免破坏.NET中的向后兼容性.为.NET 1.1编写的东西可以在.NET 4.5中编译和运行,通常没有任何更改.中断更改通常来自编译器更改,而不是框架更改,例如foreachlambda中使用的变量在C#5和更新版本中表现不同.

还有就是用没有真正的理由ThreadPool.QueueUserWorkItem,当你有Task.Run.

一个终点:具有讽刺意味的是,事情实际上已经完全循环了HostingEnvironment.QueueBackgroundWorkItem(...).它允许您在ASP.NET环境中的后台线程上运行某些东西,并让后台工作通知AppDomainWeb服务器关闭(在长时间不活动时经常会发生这种情况).

  • 我非常不同意这样的评论:“当你有 Task.Run 时,没有真正的理由使用 ThreadPool.QueueUserWorkItem。”。至少可以说它是不完整的。正如另一位评论者(zh chen)提到的:Task.Run,​​如果不被观察,将会吃掉错误,而 ThreadPool.QueueUserWorkItem 将作为未处理的异常传播。在我看来,这总是比让错误未被发现更好。在某些情况下,任务会更好、更容易编程,但在不了解所有后果的情况下盲目用“新”模式替换“旧”模式绝不是好主意。 (6认同)
  • 不,它不会,Task.Run返回的任务对象具有内部静态根,因此当线程处于运行状态时,它不适合使用GC。 (2认同)

zh *_*hen 7

ThreadPool.QueueUserWorkItemTask.Run我最近意识到的一个区别是它们处理异常的方式。

如果ThreadPool.QueueUserWorkItem未处理的异常发生在内部并且未被全局异常处理程序处理,它将使父线程崩溃。另一方面,Task.Run线程的未处理异常不会传播,直到您awaitTask.Wait