Daniel Hilgarth
Daniel Hilgarth

Reputation: 174279

ThreadPool.QueueUserWorkItem - Order not preserved?

I just noticed that the order of callbacks queued via ThreadPool.QueueUserWorkItem is not deterministic, it certainly isn't the order the callbacks have been passed in.

This can be verified with the following simple program:

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

        Thread.Sleep(1000);
    }

The output of one run is:

0 3 8 9 1 2 5 4 6 7

The name suggests that the order is preserved.

Is there a way to make sure that the order is preserved?
If not, what alternative implementation do you suggest?

Upvotes: 4

Views: 3260

Answers (4)

Boppity Bop
Boppity Bop

Reputation: 10463

The name suggests that the order is preserved.

the 'queue' in the name means that the items queued for the execution in the thread pool threads.. which means - if the thread pool threads were busy all but one - in that case your items would be queued one by one in the order you enqueued them. but because that is unlikely the items are going to first available background thread and then executed concurrently.

Upvotes: 1

Peter Ruderman
Peter Ruderman

Reputation: 12485

There is no way to preserve the order. The purpose of the thread pool is to execute independent tasks in parallel. The order in which those tasks start and finish is, by its nature, highly nondeterministic. If you need subtasks to start and finish in a particular order, then you can't parallelize them.

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

    Thread.Sleep(1000);
}

To clarify: the order of tasks within the thread pool queue is preserved, but the order in which they actually execute is nondeterministic.

Upvotes: 6

Wes Cumberland
Wes Cumberland

Reputation: 1338

If you want the tasks to run in serial but on a different thread than the calling thread, then you should look into the EventLoopScheduler in the Reactive Extensions. It allows you to schedule units of work on a particular worker thread.

Upvotes: 6

Jord&#227;o
Jord&#227;o

Reputation: 56457

I'm not sure if the order of starting the tasks is preserved or not. But, since all queued work items run asynchronously, you can't guarantee the order of execution anyway.

If you want to preserve the order, one option is to run the work items serially, not from the thread pool. Another is to schedule the second job inside the first, etc... Yet another is to use wait handles to synchronize the work.

Upvotes: 4

Related Questions