任务与线程的差异

我是并行编程的新手。. net中有两个类可用:TaskThread

所以,我的问题是:

  • 这些类之间的区别是什么?
  • 什么时候使用ThreadTask更好(反之亦然)?
369310 次浏览

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

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

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

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

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

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

    你不能使用Abort/ThreadAbortedException,你应该支持 在你的“业务代码”中定期测试token.IsCancellationRequested标志(也避免长时间或超时连接,例如到db,否则你将永远没有机会测试这个标志)。基于类似的原因,Thread.Sleep(delay)调用应该被Task.Delay(delay, token)调用取代(在内部传递令牌以有可能中断延迟)
  1. 任务中没有线程的SuspendResume方法功能。 task实例不能重用

  2. 但是你有两个新工具:

    一)延续

    // 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) 嵌套/子任务

    //StartNew - starts task immediately, parent ends whith child
    var parent = Task.Factory.StartNew
    (() => {
    var child = Task.Factory.StartNew(() =>
    {
    //...
    });
    },
    TaskCreationOptions.AttachedToParent
    );
    
  3. 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.

  4. 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) .

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

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

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

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