Differences between multithreading and multitasking in C#
Possible Duplicate:
What is the difference between task and thread?
我理解标题本身可能看起来是一个重复的问题,但我确实已经阅读了所有与这个主题相关的文章,仍然不太了解程序的行为。
我目前正在编写一个小程序,检查大约1000个电子邮件帐户。毫无疑问,我觉得多线程或多任务是正确的方法,因为每个线程/任务的计算成本不高,但每个线程的持续时间严重依赖于网络I/O。
我认为在这种情况下,将线程/任务的数量设置为比核心数量大得多的数量也是合理的。(四个用于i5-750)。因此,我将线程或任务的数量设置为100。
使用任务编写的代码段:
1 2 3 4 5 6 7 8 9 10 11 | 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); |
使用线程编写的相同代码段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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); |
那么这两者之间的本质区别是什么呢?
任务不一定与线程对应。它们将由任务库以比线程代码更有效的方式调度到线程池线程。
线程的创建成本相当高。当线程可用时,任务将排队并重用它们,因此当一个线程等待网络IO时,它实际上可以重用以执行另一个任务。空闲的线程是浪费的资源。您只能(同时)执行与处理器核心计数相对应的线程数,因此100个线程意味着对所有核心的上下文切换至少为25次。
如果使用任务,只需将所有1000个电子邮件处理任务排队,而不是将它们成批处理,然后让它撕开。任务库将处理运行它的线程数。
排序快速答案是任务不等于线程。任务在任务调度程序中排队,然后在线程上执行,但排队100个任务并不意味着您将有100个线程在运行。
通常,任务将在线程池中的线程上运行,线程池的大小是有限的。一旦所有这些线程都忙了,那么您的任务就必须等待一个线程可用来执行您的任务。也可以使用适当的任务调度器在诸如UI线程之类的事情上对它们进行排队,在这种情况下,它们最终由UI线程的消息循环同步运行(这在与UI交互时很有用)。
在任务示例中,不需要实际限制已启动的任务数,因为这些任务将已经排队,并且必须等到有线程可以运行它们。这可能是最好的方法,因为您让系统根据系统可以处理的内容来确定线程的最大数量,而不是假设您有足够的CPU/内存来处理它。
然而,使用线程的示例意味着您一定会增加所分配线程的数量。