任务和线程的区别是什么?

在c# 4.0中,在System.Threading.Tasks命名空间中有TaskThreadTask之间的真正区别是什么?我做了一些样本程序(从MSDN的帮助),为了我自己的学习

Parallel.Invoke
Parallel.For
Parallel.ForEach

但有很多怀疑,因为想法不是很清楚。

我最初在Stackoverflow中搜索了类似类型的问题,但可能是这个问题的标题我无法得到相同的答案。如果有人知道之前贴在这里的相同类型的问题,请提供链接的参考。

249588 次浏览

任务是你想要完成的事情。

线程是执行该任务的许多可能的工作线程之一。

在。net 4.0术语中,任务表示异步操作。线程通过将工作分解成块并分配给单独的线程来完成该操作。

在计算机科学术语中,Task未来承诺。(有些人使用这两个术语的同义词,有些人使用它们不同,没有人能就精确的的定义达成一致。)基本上,Task<T> "承诺;我想给你回一个T,但不是现在,亲爱的,我有点忙,你为什么不待会儿再来呢?

Thread是实现这个承诺的一种方式。但并不是每个Task都需要一个全新的Thread。(事实上,创建线程通常是不可取的,因为这样做比从线程池中重用现有线程要昂贵得多。稍后再详细说明。)如果您正在等待的值来自文件系统、数据库或网络,那么当线程可以为其他请求提供服务时,就不需要等待数据了。相反,Task可能会在值准备好时注册一个回调来接收它们。

特别是,Task没有为什么,这是因为它需要很长时间才能返回值。它可能是它需要很长时间来计算,或者它可能需要很长时间来获取。只有在前一种情况下,才能使用Thread来运行Task。(在。net中,线程是非常昂贵的,所以你通常会尽量避免使用它们,只有当你想在多个cpu上运行多个繁重的计算时才会使用它们。例如,在Windows中,一个线程的重量是12 KiByte(我认为),在Linux中,一个线程的重量只有4 KiByte,在Erlang/BEAM中甚至只有400字节。在。net中,它是1 MiByte!)

你可以使用Task来指定你想做什么,然后用Thread来附加那个Task。这样Task将在新创建的Thread中执行,而不是在GUI线程中执行。

使用TaskTaskFactory.StartNew(Action action)。在这里你执行一个委托,所以如果你没有使用任何线程,它将在同一个线程(GUI线程)中执行。如果你提到一个线程,你可以在不同的线程中执行这个Task。这是一个不必要的工作,因为您可以直接执行委托或将该委托附加到线程,并在该线程中执行该委托。所以不要用它。这是不必要的。如果你打算优化你的软件,这是一个很好的候选删除。

**请注意Actiondelegate

Task就像一个你想要执行的操作。线程通过多个进程节点帮助管理这些操作。Task是一个轻量级的选项,因为线程会导致复杂的代码管理 我建议你从MSDN(世界上最好的)总是

任务

线程

线程

裸金属的东西,你可能不需要使用它,你可能可以使用LongRunning任务,并从TPL -任务并行库中受益,包括在。net Framework 4(2002年2月)和更高版本(也包括。net Core)中。

任务

线程之上的抽象。它使用线程池(除非你将任务指定为LongRunning操作,否则将在底层为你创建一个新线程)。

线程池

顾名思义:线程池。这是. net框架为您处理有限数量的线程。为什么?因为在只有8核的处理器上打开100个线程来执行昂贵的CPU操作绝对不是一个好主意。框架将为您维护这个池,重用线程(不是在每次操作时创建/杀死它们),并以一种CPU不会烧毁的方式并行执行其中一些线程。

好的,但是什么时候使用它们呢?

在简历中:总是使用任务。

任务是一种抽象,因此使用起来容易得多。我建议你总是尝试使用任务,如果你遇到一些问题,让你需要自己处理一个线程(可能有1%的时间),那么就使用线程。

但请注意:

  • I / O绑定:对于I/O绑定操作(数据库调用,读/写文件,api调用等)避免使用普通任务,使用LongRunning任务(或者线程(如果需要的话))。因为使用任务将导致您进入一个线程池,其中有几个线程繁忙,而许多其他任务正在等待轮到它使用池。
  • CPU绑定:对于CPU绑定的操作,只使用正常的任务(内部将使用线程池),并且是快乐的。

除以上几点外,最好了解以下几点:

  1. 任务默认为后台任务。你不能有前台任务。另一方面,线程可以是后台的,也可以是前台的(使用IsBackground属性来改变行为)。
  2. 在线程池中创建的任务可以回收线程,从而节省资源。所以在大多数情况下,任务应该是你的默认选择。
  3. 如果操作很快,使用任务而不是线程要好得多。对于长时间运行的操作,任务没有提供比线程更多的优势。

我通常使用Task与Winforms和简单的后台工作人员交互,使其不冻结UI。下面是一个我更喜欢使用Task的例子。

private async void buttonDownload_Click(object sender, EventArgs e)
{
buttonDownload.Enabled = false;
await Task.Run(() => {
using (var client = new WebClient())
{
client.DownloadFile("http://example.com/file.mpeg", "file.mpeg");
}
})
buttonDownload.Enabled = true;
}

VS

private void buttonDownload_Click(object sender, EventArgs e)
{
buttonDownload.Enabled = false;
Thread t = new Thread(() =>
{
using (var client = new WebClient())
{
client.DownloadFile("http://example.com/file.mpeg", "file.mpeg");
}
this.Invoke((MethodInvoker)delegate()
{
buttonDownload.Enabled = true;
});
});
t.IsBackground = true;
t.Start();
}

区别在于你不需要使用MethodInvoker和更短的代码。

Task可以被看作是一种异步和并行执行某项任务的简便方法。

通常一个任务是所有你需要的,我不记得如果我曾经使用线程除了实验。

你可以用线程(付出很多努力)完成和用任务一样的事情。

线程

int result = 0;
Thread thread = new System.Threading.Thread(() => {
result = 1;
});
thread.Start();
thread.Join();
Console.WriteLine(result); //is 1

任务

int result = await Task.Run(() => {
return 1;
});
Console.WriteLine(result); //is 1

默认情况下,任务将使用Threadpool,这节省了资源,因为创建线程的开销很大。您可以将Task视为线程的更高级别抽象。

正如这篇文章指出的那样,Task在Thread上提供了以下强大的特性。

  • 任务被调优以利用多核处理器。

  • 如果系统有多个task,那么它将使用CLR线程池 在内部,因此没有与创建相关的开销 一个使用thread的专用线程。也减少了语境

    .线程间时间切换
  • Task可以返回一个结果。没有从线程返回结果的直接机制。

  • 等待一组任务,没有信号构造。

  • 我们可以将任务链接在一起,一个接一个地执行。

  • 当一个任务从开始时建立父/子关系 另一个任务。< / p >

  • 子任务异常可以传播到父任务。

  • 任务通过使用取消令牌来支持取消。

  • 异步实现在Task中很容易,使用asyncawait关键词。< / p >