views:

97

answers:

2

I have a Backgroundworker whose purpose is to run jobs sequentially in the background. Now one job is implemented in multithreading way. That mean, the Backgroundworker will create several threads. I use Task Parallel Library so I use the Task.Factory.StartNew to create multiple Tasks.

After the tasks are run, the Backgroundworker waits all of them to finish.

Now I print the Backgroundworker's ManagedThreadID and all the tasks' ManagedThreadIDs. I found that the BackgroundWorker's ManagedThreadID is always the same as the first task's ManagedThreadID. I think this shouldn't happen so I cannot explain. I think the Backgroundworker's thread must be different to all the tasks it creates so the ManagedThreadIDs must be all different from each other.

Can anyone explain why this scenario happens? Thank you very much.

Edit:

The code is similar to this:

Backgroundworker.Run(){
    // Print Thread.CurrentThread.ManagedThreadID.
    var task = Task.Factory.StartNew(action1); // action1, action2 also print ManagedThredID.
    taskList.Add(task);
    task = Task.Factory.StartNew(action2);
    taskList.Add(task);
    ... // Several other tasks.

    foreach(var task in taskList) task.Wait();
}

You will find that one task has the same ManagedThreadID as the Backgroundworker.

+2  A: 

The Background worker draws threads from the thread pool as well as TPL. What might happen is that the background worker is started, it draws a thread from the pool and fires TPL threads and returns immediately the thread to the pool. By the time TPL's first task is executed TPL draws a thread from the pool and it happens that it picks the same thread as the one once used by the background worker.

Of course that's just a supposition which cannot be verified because you haven't shown your code.

Darin Dimitrov
But the OP mentions that the worker explicitly waits for all tasks to complete.
João Angelo
@João: And while you wait something else can use your Thread.
Henk Holterman
@Henk Holterman, my doubts are related to the possibility of really be something else or just one of the tasks. It's a matter of where the optimization is, if it's in TPL the thread is not returned to the pool but a task execution is inlined due to the call to `Wait`. Basically I just don't totally agree with the statement of the worker thread being returned to the pool.
João Angelo
+4  A: 

I would go on a limb here and guess that the TPL is smart enough to reuse the BackgroundWorker thread. Since the worker waits for all tasks to complete running one task in the same thread is probably an optimization.

From further investigation, what you are seeing is a result of the expected behaviour of the Task.Wait method. You can read more at Task.Wait and "Inlining" on the Parallel Programming Team blog.

If the Task being Wait’d on has already started execution, Wait has to block. However, if it hasn’t started executing, Wait may be able to pull the target task out of the scheduler to which it was queued and execute it inline on the current thread.

João Angelo