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

Parallel.Invoke 
Parallel.For 
Parallel.ForEach 

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

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


当前回答

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

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

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

线程

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

Task

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

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

正如本文所指出的,Task在Thread上提供了以下功能强大的特性。

Tasks are tuned for leveraging multicore processors. If the system has multiple Tasks then it makes use of the CLR thread pool internally, and so does not have the overhead associated with creating a dedicated thread using the Thread. Also reduces the context switching time among multiple threads. Task can return a result. There is no direct mechanism to return the result from thread. Wait on a set of Tasks, without a signaling construct. We can chain Tasks together to execute one after the other. Establish a parent/child relationship when one task is started from another task. A child Task Exception can propagate to parent task. Tasks support cancellation through the use of cancellation tokens. Asynchronous implementation is easy in Task, using async and await keywords.

其他回答

我通常使用任务与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和更短的代码。

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

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

线程

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

任务

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

线程池

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

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

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

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

但请注意:

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

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

线程

您可以使用Task指定要做什么,然后将该任务附加到线程中。这样任务就会在新创建的线程中执行,而不是在GUI线程上。

Use Task with the TaskFactory.StartNew(Action action). In here you execute a delegate so if you didn't use any thread it would be executed in the same thread (GUI thread). If you mention a thread you can execute this Task in a different thread. This is an unnecessary work cause you can directly execute the delegate or attach that delegate to a thread and execute that delegate in that thread. So don't use it. it's just unnecessary. If you intend to optimize your software this is a good candidate to be removed.

**请注意Action是一个委托。