. net中有两个类:任务和线程。

这些类之间的区别是什么? 什么时候使用线程比任务更好(反之亦然)?


当前回答

Thread类用于在Windows中创建和操作线程。

任务表示一些异步操作,是任务并行库(Task Parallel Library)的一部分,任务并行库是一组用于异步并行运行任务的api。

在过去的日子里(即在TPL之前),使用Thread类是在后台或并行运行代码的标准方法之一(更好的选择通常是使用ThreadPool),然而这很麻烦,而且有几个缺点,其中最重要的是创建一个全新的线程来在后台执行任务的性能开销。

如今,使用任务和TPL在90%的情况下是一个更好的解决方案,因为它提供了抽象,允许更有效地使用系统资源。我想在某些情况下,您需要显式地控制运行代码的线程,但是一般来说,如果您想异步运行某些内容,那么您的第一个调用端口应该是TPL。

其他回答

通常你听到的任务是一个比线程更高级别的概念…这就是这个短语的意思:

You can't use Abort/ThreadAbortedException, you should support cancel event in your "business code" periodically testing token.IsCancellationRequested flag (also avoid long or timeoutless connections e.g. to db, otherwise you will never get a chance to test this flag). By the similar reason Thread.Sleep(delay) call should be replaced with Task.Delay(delay, token) call (passing token inside to have possibility to interrupt delay). There are no thread's Suspend and Resume methods functionality with tasks. Instance of task can't be reused either. But you get two new tools: a) continuations // continuation with ContinueWhenAll - execute the delegate, when ALL // tasks[] had been finished; other option is ContinueWhenAny Task.Factory.ContinueWhenAll( tasks, () => { int answer = tasks[0].Result + tasks[1].Result; Console.WriteLine("The answer is {0}", answer); } ); b) nested/child tasks //StartNew - starts task immediately, parent ends whith child var parent = Task.Factory.StartNew (() => { var child = Task.Factory.StartNew(() => { //... }); }, TaskCreationOptions.AttachedToParent ); So system thread is completely hidden from task, but still task's code is executed in the concrete system thread. System threads are resources for tasks and ofcourse there is still thread pool under the hood of task's parallel execution. There can be different strategies how thread get new tasks to execute. Another shared resource TaskScheduler cares about it. Some problems that TaskScheduler solves 1) prefer to execute task and its conitnuation in the same thread minimizing switching cost - aka inline execution) 2) prefer execute tasks in an order they were started - aka PreferFairness 3) more effective distribution of tasks between inactive threads depending on "prior knowledge of tasks activity" - aka Work Stealing. Important: in general "async" is not same as "parallel". Playing with TaskScheduler options you can setup async tasks be executed in one thread synchronously. To express parallel code execution higher abstractions (than Tasks) could be used: Parallel.ForEach, PLINQ, Dataflow. Tasks are integrated with C# async/await features aka Promise Model, e.g there requestButton.Clicked += async (o, e) => ProcessResponce(await client.RequestAsync(e.ResourceName)); the execution of client.RequestAsync will not block UI thread. Important: under the hood Clicked delegate call is absolutely regular (all threading is done by compiler).

That is enough to make a choice. If you need to support Cancel functionality of calling legacy API that tends to hang (e.g. timeoutless connection) and for this case supports Thread.Abort(), or if you are creating multithread background calculations and want to optimize switching between threads using Suspend/Resume, that means to manage parallel execution manually - stay with Thread. Otherwise go to Tasks because of they will give you easy manipulate on groups of them, are integrated into the language and make developers more productive - Task Parallel Library (TPL) .

线程是一个较低层次的概念:如果你直接启动一个线程,你知道它将是一个单独的线程,而不是在线程池中执行。

任务不仅仅是“在哪里运行一些代码”的抽象概念——它实际上只是“对未来结果的承诺”。举几个不同的例子:

的任务。延迟不需要任何实际的CPU时间;这就像在未来设置一个计时器 WebClient返回的任务。DownloadStringTaskAsync不会在本地占用太多CPU时间;它表示的结果可能会花费大部分时间在网络延迟或远程工作(在web服务器上) task . run()返回的任务实际上是在说“我想让你单独执行这段代码”;代码执行的确切线程取决于许多因素。

请注意,Task<T>抽象对于c# 5中的异步支持至关重要。

一般来说,我建议您尽可能使用更高级别的抽象:在现代c#代码中,您几乎不需要显式地启动自己的线程。

Thread类用于在Windows中创建和操作线程。

任务表示一些异步操作,是任务并行库(Task Parallel Library)的一部分,任务并行库是一组用于异步并行运行任务的api。

在过去的日子里(即在TPL之前),使用Thread类是在后台或并行运行代码的标准方法之一(更好的选择通常是使用ThreadPool),然而这很麻烦,而且有几个缺点,其中最重要的是创建一个全新的线程来在后台执行任务的性能开销。

如今,使用任务和TPL在90%的情况下是一个更好的解决方案,因为它提供了抽象,允许更有效地使用系统资源。我想在某些情况下,您需要显式地控制运行代码的线程,但是一般来说,如果您想异步运行某些内容,那么您的第一个调用端口应该是TPL。