views:

80

answers:

2

I have some simple code in which the main Thread is creating a new Task. The task in turn spawns multiple child tasks. The main Thread does a 'wait' on the parent Task. I'm observing that I don't get the same output across multiple runs of the program. In the code below I'm printing out the value of the iteration variable in each task but across different runs only subsets get printed out. I understand that the execution is not ordered but it would still have to be complete in that I'm expecting 100 numbers to get printed out(in no particular order). Does calling Wait does not wait for all child tasks to complete? I'm running VS2010 Team system Beta1

 static void Main(string[] args)
    {
        Console.WriteLine("Main executing on ThreadID:- " + Thread.CurrentThread.ManagedThreadId.ToString());

        var task = Task.Factory.StartNew(WriteNumbers);
        task.Wait();

    }

    private static void WriteNumbers()
    {
        Console.WriteLine("WriteNumbers executing on ThreadID:- " + Thread.CurrentThread.ManagedThreadId.ToString());
        for (int i = 0; i < 100; i++)
        {
            int localInt = i;
            Task.Factory.StartNew(() => 
                {
                   Write(localInt);
                }, TaskCreationOptions.DetachedFromParent);
        }
    }

    private static void Write(int i)
    {            
        Console.WriteLine("Worker Thread executing on ThreadID:-" + Thread.CurrentThread.ManagedThreadId.ToString() + " Value:" + i.ToString());
    }
+3  A: 

Per MSDN, you need more waiting or other synchronization, and I quote: """ When you wait on a task, you implicitly wait on all children of that task, unless those children were created by using the DetachedFromParent option. Any detached children must be waited on separately. """

Here, main waits on parent, but since parent's children were indeed created as detached, that does not make main implicitly wait on the children as well, so main (and therefore the whole process) can and often will terminate before some child task has had a chance to run.

Alex Martelli
Yup, I realized my mistake seconds after i posted (duh)
Abhijeet Patel
+2  A: 

My mistake: I accidentally used the DetachedFromParent option when creating the children

 Task.Factory.StartNew(() => 
            {
               Write(localInt);
            }, TaskCreationOptions.DetachedFromParent);
Abhijeet Patel
Right, that's what I explained in my answer above (just before you posted this "self-answer"). I could not, of course, know that it was a mistake -- it would be a natural thing to want (let all grandchildren run free and have just one wait in the main), it's just apparently not workable in the Task Parallel Library as it stands today.
Alex Martelli
No worries...I think that the paradigm that you mentioned makes a lot of sense, in a way you are giving up ownership of your children so its upto you to explicitly "track" these tasks and ensure that they complete if you are depending on the results of these tasks for any computation
Abhijeet Patel
PS - i marked your solution as the answer since you posted it right before i realized my screw up
Abhijeet Patel