Task Factories

  1. 1.   What is the purpose of a TaskFactory?

 

We need a TaskFactory when we have to repeatedly create tasks with the same parameters. Using a TaskFactory we can achieve three goals:

  1. Create ordinary Tasks (via StartNew()).
  2.  Continuations with multiple antecedents (via ContinueWhenAll() or  ContinueWhenAny()).
  3. Tasks that wrap methods that follow the asynchronous programming model (via FromAsync()).

Sample 1:

Task parent = new Task(() =>

{

    CancellationTokenSource cts = new CancellationTokenSource();

    TaskFactory<int> taskFactory = new TaskFactory<int>(cts.Token,

        TaskCreationOptions.AttachedToParent,

        TaskContinuationOptions.ExecuteSynchronously,

        TaskScheduler.Default);

    Task<int>[] childTasks = new[]

    {

        taskFactory.StartNew(

            () => GetResult(100)

        , cts.Token),

        taskFactory.StartNew( () =>

            GetResult(200)

            , cts.Token

        ),

        taskFactory.StartNew( () =>

            GetResult(int.MaxValue)

            , cts.Token)                   

    };

    foreach (Task<int> childTask in childTasks)

    {

        childTask

            .ContinueWith(t => cts.Cancel(), TaskContinuationOptions.OnlyOnFaulted);

    }

    taskFactory.ContinueWhenAll(

        childTasks

        , selectedTasks => selectedTasks

            .Where(t => !t.IsCanceled && !t.IsFaulted)

            .Max(t => t.Result)

        , CancellationToken.None)

        .ContinueWith(t => Console.WriteLine(t.Result), TaskContinuationOptions.ExecuteSynchronously);

});

parent.ContinueWith(task =>

{

    StringBuilder sb = new StringBuilder(task.Exception.InnerExceptions.Count);

    foreach (Exception exception in task.Exception.InnerExceptions)

    {

        sb.Append(exception.ToString());

    }

    Console.WriteLine(sb.ToString());

}, TaskContinuationOptions.OnlyOnFaulted);

parent.Start();