2

I'm trying to create an extension method that will make any task attached to parent.

Extension code:

internal static class TaskHelpers
{
    public static Task AttachToParrent(this Task task)
    {
        var tsc = new TaskCompletionSource<Task>(task.CreationOptions &    TaskCreationOptions.AttachedToParent);

        task.ContinueWith(_ => tsc.TrySetResult(task), TaskContinuationOptions.OnlyOnRanToCompletion);

        task.ContinueWith(t => tsc.TrySetException(task.Exception ?? new AggregateException(new ApplicationException("Unknown"))), TaskContinuationOptions.OnlyOnFaulted);

        task.ContinueWith(t => tsc.TrySetCanceled(), TaskContinuationOptions.OnlyOnCanceled);

        return tsc.Task.Unwrap();
    }
}

Test Code:

  static void Main(string[] args)
    {
        var  cancellationTokenSource = new CancellationTokenSource();

        var task1 = Task.Factory.StartNew(() =>
        {
            var task2 = Task.Factory.StartNew(() =>
            {
                for (int i = 0; i < 5; i++)
                {


                    if (!cancellationTokenSource.IsCancellationRequested)
                    {
                        Console.WriteLine(i);

                        Thread.Sleep(5000);
                    }
                    else
                    {
                        Console.WriteLine("Loop cancelled.");

                        break;
                    }
                }

            }, cancellationTokenSource.Token).AttachToParrent();

            var task3 = Task.Factory.StartNew(() =>
            {
                for (int i = 0; i < 5; i++)
                {

                    if (!cancellationTokenSource.IsCancellationRequested)
                    {
                        Console.WriteLine(i*10);

                        Thread.Sleep(5000);
                    }
                    else
                    {
                        Console.WriteLine("Loop cancelled.");

                        break;
                    }
                }

            }, cancellationTokenSource.Token).AttachToParrent();
        }, cancellationTokenSource.Token);

        Console.WriteLine("Enter to cancel");

        Console.ReadKey();

        cancellationTokenSource.Cancel();

        Console.WriteLine("Waiting To Be Cancelled");

        task1.Wait();

        Console.WriteLine("Task Cancelled");

        Console.ReadKey();
    }

Parent task is cancelled immediately without waiting for inner tasks to complete. How can I solve it, as an input I'm getting a task which I'm execution in my parent dispatcher task. I want to execute any task as attached to parent.

schizofreindly
  • 177
  • 2
  • 13

2 Answers2

1

Just supply TaskCreationOptions.AttachedToParentwhen calling Task.Factory.StartNew (only when creating the child tasks):

var task2 = Task.Factory.StartNew(..., cancellationTokenSource.Token, TaskCreationOptions.AttachedToParent, TaskScheduler.Current);

For more information about Attached/Detached tasks: see MSDN

a-ctor
  • 3,568
  • 27
  • 41
1

Found the problem the problem is in

var tsc = new TaskCompletionSource<Task>(task.CreationOptions &    TaskCreationOptions.AttachedToParent); 

The tsc,CreationOptions remains as nooptions.

Changed to

var tsc = new TaskCompletionSource<Task>(TaskCreationOptions.AttachedToParent); 

Now everything works.

schizofreindly
  • 177
  • 2
  • 13
  • Maybe you meant to use `|` (bitwise OR)? Bitwise AND (`&`) is a logical AND-ing. In English when you say “and” sometimes you mean “additionally” whereas in logic (or, at least here) it always means “the intersection/overlap”. – binki May 23 '17 at 20:11