我想了解Parralel.For
和ThreadPool.QueueUserWorkItem
之间的差异。ThreadPool.QueueUserWorkItem vs Parallel.For
硬件&软件:
- 英特尔酷睿i5(四核)
- Windows 7的64位教授
- DOTNET的4.5
案例1级的代码:线程池
for (int index = 0; index < 5; index++)
{
ThreadPool.QueueUserWorkItem((indexParam) =>
{
int threadID = Thread.CurrentThread.ManagedThreadId;
Thread.Sleep(1000);
BeginInvoke((Action)delegate { listBox1.Items.Add("Completed " + indexParam.ToString() + " using thread " + threadID.ToString() + " (" + DateTime.Now.Second.ToString() + "." + DateTime.Now.Millisecond.ToString("000") + ")"); });
}, index);
}
输出:
使用螺纹10(45.871)
使用螺纹11(45.875)已完成1
使用螺纹12(45.875)完成2
使用螺纹13已完成3(45.875)完成0
使用螺纹10(46.869)
案例完成4 2代码:的Parallel.For
ParallelLoopResult result = Parallel.For(0, 5, (int index, ParallelLoopState loopState) =>
{
int threadID = Thread.CurrentThread.ManagedThreadId;
Thread.Sleep(1000);
BeginInvoke((Action)delegate { listBox1.Items.Add("Completed " + index.ToString() + " using thread " + threadID.ToString() + " (" + DateTime.Now.Second.ToString() + "." + DateTime.Now.Millisecond.ToString("000") + ")"); });
});
输出:
使用螺纹10(16.923)
使用螺纹11(16.925)已完成1
使用螺纹12(16.925)完成2
使用螺纹13已完成3完成0 (16.926)
已完成4使用线程14(16.926)
问题:
从案例1的结果看来,只有四个线程处于活动状态,然后第一个空闲线程才用于完成最终任务。在情况2中,看起来五个线程立即专用并且“同时”执行。
为什么QueueUserWorkItem的线程处理不使用第五个线程,比如并行类?
(ThreadPool.GetAvailableThreads(...)
确认1023个工作线程可用)。
道歉 - 输出2的结果中存在拼写错误。我更新了它 - 真正使用了第五个线程。 – Fortmann
毫无疑问,线程可以在几毫秒内启动(在ThreadPool的情况下,现有线程可以更快地分派)。为什么线程池决定不派遣第五个线程后,我已经明确要求它为第五个任务做到这一点?前四个和最后一个线程之间的延迟恰好是一秒,这表明延迟不是由线程管理员造成的,管理员正在等待前四个中的一个完成。 – Fortmann
创建线程可能是一项昂贵的任务。如果您要求它运行1000个任务会怎么样?它不会启动1000个线程,但它会缓慢增加,直到达到平衡。我怀疑如果你将睡眠时间增加到5秒作为测试,你会看到线程池中的算法决定启动一个新的线程。我个人使用一个线程池来处理负载变化很大的服务。游泳池将有40个线程活动到200个任意位置。在短期内,任务可能需要更长时间,但平均而言,游泳池在找到最佳性能点方面做得很好。 – AFrieze