ThreadPool.QueueUserWorkItem - 订单未保存?

时间:2013-01-24 16:20:05

标签: c# .net multithreading threadpool

我只是注意到通过ThreadPool.QueueUserWorkItem排队的回调顺序不是确定性的,它肯定不是传递回调的顺序。

这可以通过以下简单程序进行验证:

    private static void Main()
    {
        for (var i = 0; i < 10; ++i)
            ThreadPool.QueueUserWorkItem(Console.Write, i + " ");

        Thread.Sleep(1000);
    }

一次运行的输出是:

0 3 8 9 1 2 5 4 6 7

该名称表明订单已保留。

有没有办法确保订单得到保留?
如果没有,您建议采用哪种替代实施方案?

4 个答案:

答案 0 :(得分:5)

无法保留订单。线程池的目的是并行执行独立的任务。从本质上讲,这些任务的开始和结束顺序是高度不确定的。如果您需要以特定顺序开始和结束子任务,那么您无法将它们并行化。

private static void Main()
{
    for (var i = 0; i < 10; ++i)
        Console.Write(i + " ");

    Thread.Sleep(1000);
}

澄清一下:线程池队列中的任务顺序是保留的,但它们实际执行的顺序是不确定的。

答案 1 :(得分:4)

如果您希望任务在串行但在与调用线程不同的线程上运行,那么您应该查看EventLoopScheduler中的Reactive Extensions。它允许您在特定工作线程上安排工作单元。

答案 2 :(得分:2)

我不确定是否保留启动任务的顺序。但是,由于所有排队的工作项都是异步运行的,因此无论如何都无法保证 execution 的顺序。

如果要保留订单,一个选项是从线程池中串行运行工作项 not 。另一个是安排第二个作业中第一个等等......另一个是使用等待句柄来同步工作。

答案 3 :(得分:1)

  

该名称表明订单已保留。

名称中的“队列”意味着在线程池线程中排队等待执行的项目...这意味着 - 如果线程池线程忙于除了一个 - 在这种情况下,您的项目将逐个排队按照你排队的顺序。但是因为这不太可能是项目第一个可用的后台线程,然后同时执行。

相关问题