- 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:
- Create ordinary Tasks (via StartNew()).
- Continuations with multiple antecedents (via ContinueWhenAll() or ContinueWhenAny()).
- 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();