我应该注意到在.net 4.0中使用任务和线程的区别吗?
本文关键字:线程 任务 区别 注意到 net 我应该 | 更新日期: 2023-09-27 18:15:55
我更新了我的代码,使用任务而不是线程....
查看内存使用和CPU,我没有注意到多核PC上的任何改进,这是预期的吗?我的应用程序在运行时基本上在不同的对象中启动线程/任务…
我所做的只是一个简单的
Task a = new Task(...)
a.Start();
使用任务而不是线程有各种各样的含义,但性能不是主要的(假设您没有创建大量的线程)。几个关键的区别:
- 默认的TaskScheduler将使用线程池,所以一些任务可能不会启动,直到其他挂起的任务完成。如果直接使用Thread,每次使用都会启动一个新的Thread。
- 当Task中发生异常时,它被包装成AggregateException,当调用代码等待Task完成或在Task上注册延续时可以接收该异常。这是因为你也可以做一些事情,比如等待多个任务完成,在这种情况下,多个异常可以被抛出和聚合。
- 如果您没有观察到由Task抛出的未处理异常,那么它将(好吧,可能)最终由Task的终结器抛出,这是特别讨厌的。我总是推荐钩住TaskScheduler。UnobservedTaskException事件,这样你至少可以在应用程序崩溃之前记录这些失败。这与线程异常不同,线程异常显示在AppDomain中。UnhandledException事件。
如果您简单地将Thread
的每次使用都替换为Task
,并且不做任何其他更改,那么我期望几乎相同的性能。Task
API实际上就是这样,它是一个基于现有结构集的API。在底层,它使用线程来调度它的活动,因此具有类似的性能特征。
Task
的伟大之处在于你可以用它们做新的事情
- 与
ContinueWith
的合成 取消 - 层次
- 等等…
Takss vs. Threads的一大改进是您可以轻松地构建任务链。你可以指定一个任务应该在前一个任务("OnSuccess","OnError",等等)之后何时开始,你可以指定是否应该有一个同步上下文切换。这给了你一个很好的机会在后台运行一个长时间运行的任务,然后在UI线程上运行一个UI刷新任务。
如果你使用的是。net 4.0,那么你可以使用Parallel。像这样调用方法
Parallel.Invoke(()=> {
// What ever code you add here will get threaded.
});
查看更多信息http://msdn.microsoft.com/en-us/library/dd992634.aspx
如果您的原始代码或转换代码不完全利用CPU,则会看到差异。例如,如果原始代码总是将线程数量限制在2,那么在四核机器上,它将以大约50%的负载运行手动创建的线程,并且可能以100%的负载运行任务(如果您的任务实际上可以并行化)。因此,从性能的角度来看,要么您的原始代码是合理的,要么两个实现都出现了类似的CPU利用率不足的问题。