5

可能重复:
任务和线程有什么区别?

我知道标题本身可能看起来是一个重复的问题,但我真的阅读了与该主题相关的所有先前帖子,但仍然不太了解程序行为。

我目前正在编写一个检查大约 1,000 个电子邮件帐户的小程序。毫无疑问,我觉得多线程或多任务处理是正确的方法,因为每个线程/任务的计算成本并不高,但每个线程的持续时间很大程度上依赖于网络 I/O。

我认为在这种情况下,将线程/任务的数量设置为远大于核心数量的数量也是合理的。(i5-750 四个)。因此,我将线程或任务的数量设置为 100。

使用 Tasks 编写的代码片段:

        const int taskCount = 100;
        var tasks = new Task[taskCount];
        var loopVal = (int) Math.Ceiling(1.0*EmailAddress.Count/taskCount);

        for (int i = 0; i < taskCount; i++)
        {
            var objContainer = new AutoCheck(i*loopVal, i*loopVal + loopVal);
            tasks[i] = new Task(objContainer.CheckMail);
            tasks[i].Start();
        }
        Task.WaitAll(tasks);

使用 Threads 编写的相同代码片段:

        const int threadCount = 100;
        var threads = new Thread[threadCount];
        var loopVal = (int)Math.Ceiling(1.0 * EmailAddress.Count / threadCount);

        for (int i = 0; i < threadCount; i++)
        {
            var objContainer = new AutoCheck(i * loopVal, i * loopVal + loopVal);
            threads[i] = new Thread(objContainer.CheckMail);
            threads[i].Start();
        }
        foreach (Thread t in threads)
            t.Join();
        runningTime.Stop();
        Console.WriteLine(runningTime.Elapsed);

那么这两者的本质区别是什么?

4

2 回答 2

7

任务不一定对应线程。它们将由任务库以比您的线程代码更有效的方式安排到线程池线程。

创建线程相当昂贵。任务将排队并在线程可用时重用它们,因此当一个线程正在等待网络 IO 时,它实际上可以被重用以执行另一个任务。闲置的线程是浪费的资源。您只能(同时)执行与您的处理器核心数相对应的线程数,因此 100 个线程意味着所有核心上的上下文切换至少 25 次。

如果使用任务,只需将所有 1000 个电子邮件处理任务排队,而不是将它们批量处理并让它撕裂。任务库将处理运行它的线程数。

于 2012-10-16T20:07:41.933 回答
0

排序快速的答案是任务不等于线程。一个任务在任务调度器中排队,然后在一个线程上执行,但是排队 100 个任务并不意味着你将有 100 个线程在运行。

通常,任务将在线程池中的一个线程上运行,该线程池具有有限的大小。一旦所有这些线程都忙了,那么您的任务将不得不等待一个线程变得可用于执行您的任务。也可以使用适当的任务调度程序将它们排列在 UI 线程等事物上,在这种情况下,它们最终由 UI 线程的消息循环同步运行(这在与 UI 交互时很有用)。

在您的任务示例中,实际上不需要限制启动的任务数量,因为这些任务已经排队并且必须等到有可用的线程来运行它们。这可能是最好的方法,因为您让系统根据系统可以处理的内容确定最大线程数,而不是假设您有足够的 CPU/内存来处理它。

而您使用线程的示例特别意味着您肯定会增加您分配的线程数。

于 2012-10-16T20:08:59.797 回答