Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parent task does not wait for child task to complete

So here is my code

Task<int[]> parent = Task.Run(() =>
{
    var result = new int[3];

    TaskFactory tf = new TaskFactory(TaskCreationOptions.AttachedToParent, TaskContinuationOptions.ExecuteSynchronously);

    for (int i = 0; i < result.Length; i++)
    {
        int j = i;
        tf.StartNew(() => result[j] = GetRandomNumber(j));
    }

    return result;
});

var finalTask = parent.ContinueWith(parentTask =>
{
    foreach (var i in parentTask.Result)
    {
        Console.WriteLine(i);   
    }
});

finalTask.Wait();

Basically I create 3 Tasks which are children of Task called parent (I guess). I excpect parent task to wait for all three child tasks to complete. After that the finalTask would be waited to execute because of finalTask.Wait(); this statemant. But things do not happen as expected. I mean the application exits before the any of GetRandomNumber calls finishes. Some part of the code in here is copied from book which stated that those parent task should wait for child task to complete which apparently is not happening. Am I missing something here ?

this is what GetRandomNumber does

public static int GetRandomNumber(int ii)
{
    Random rand = new Random();

    for (int i = 0; i < 1000000000; i++) { } // imitate some jobs

    return rand.Next(1000);
}

This code does the same thing

Task<int[]> parent = Task.Run(() =>
{
    var result = new int[3];

    for (int i = 0; i < result.Length; i++)
    {
        int j = i;
        new Task(() => result[j] = GetRandomNumber(j), TaskCreationOptions.AttachedToParent).Start();
    }

    return result;
});
like image 872
Dimitri Avatar asked Feb 18 '14 17:02

Dimitri


People also ask

What is the difference between attached and detached child tasks?

A child task can be either detached or attached. A detached child task is a task that executes independently of its parent. An attached child task is a nested task that is created with the TaskCreationOptions. AttachedToParent option whose parent does not explicitly or by default prohibit it from being attached.

What are parent tasks?

Parent Task is a high-level item within task breakdown that is specified with greater detail by a number of related sub-tasks or child tasks. It is the root task that subordinates its sub-tasks and defines how they should be performed and related to each other.

Does task wait start task?

Wait is a synchronization method that causes the calling thread to wait until the current task has completed. If the current task has not started execution, the Wait method attempts to remove the task from the scheduler and execute it inline on the current thread.


3 Answers

This behaviour is due to your use of the Task.Run method, which forbids child tasks from being attached to the parent:

The Run method is a simpler alternative to the StartNew method. It creates a task [whose] CreationOptions property value is TaskCreationOptions.DenyChildAttach.

To resolve, simply change your first line from

Task<int[]> parent = Task.Run(() =>

to

Task<int[]> parent = Task.Factory.StartNew(() =>
like image 137
Douglas Avatar answered Oct 23 '22 16:10

Douglas


In Task.Run's documentation, you'll find that it specifies

Its CreationOptions property value is TaskCreationOptions.DenyChildAttach.

So, even though you specify TaskCreationOptions.AttachedToParent, it is ignored.

like image 39
Matt Smith Avatar answered Oct 23 '22 16:10

Matt Smith


Please use the code as below:

static void RunParentTask()
    {
        Task<int[]> parent = Task.Factory.StartNew<int[]>(() =>
        {
            var results = new int[3];

            TaskFactory<int> factory = new TaskFactory<int>(TaskCreationOptions.AttachedToParent,
                                                            TaskContinuationOptions.ExecuteSynchronously);
            factory.StartNew(() => results[0] = 1);
            factory.StartNew(() => results[1] = 2);
            factory.StartNew(() => results[2] = 3);

            return results;
        });

        parent.Wait();

        foreach (var item in parent.Result)
        {
            Console.WriteLine(item);
        }
    }
like image 2
Lokesh Avatar answered Oct 23 '22 14:10

Lokesh