Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
DotNETFrameworkNotesForProfessionals.pdf
Скачиваний:
32
Добавлен:
20.05.2023
Размер:
1.82 Mб
Скачать

foreach(var task in tasks) Console.WriteLine(task.Result);

Section 42.11: Task: WaitAny

var allTasks = Enumerable.Range(1, 5).Select(n => new Task<int>(() => n)).ToArray(); var pendingTasks = allTasks.ToArray();

foreach(var task in allTasks) task.Start();

while(pendingTasks.Length > 0)

{

var finishedTask = pendingTasks[Task.WaitAny(pendingTasks)]; Console.WriteLine("Task {0} finished", finishedTask.Result); pendingTasks = pendingTasks.Except(new[] {finishedTask}).ToArray();

}

Task.WaitAll(allTasks);

Note: The final WaitAll is necessary becasue WaitAny does not cause exceptions to be observed.

Section 42.12: Task: handling exceptions (using Wait)

var task1 = Task.Run(() =>

{

Console.WriteLine("Task 1 code starting...");

throw new Exception("Oh no, exception from task 1!!");

});

var task2 = Task.Run(() =>

{

Console.WriteLine("Task 2 code starting...");

throw new Exception("Oh no, exception from task 2!!");

});

Console.WriteLine("Starting tasks..."); try

{

Task.WaitAll(task1, task2);

}

catch(AggregateException ex)

{

Console.WriteLine("Task(s) failed!"); foreach(var inner in ex.InnerExceptions)

Console.WriteLine(inner.Message);

}

Console.WriteLine("Task 1 status is: " + task1.Status); //Faulted

Console.WriteLine("Task 2 status is: " + task2.Status); //Faulted

Section 42.13: Task: handling exceptions (without using Wait)

var task1 = Task.Run(() =>

{

Console.WriteLine("Task 1 code starting...");

throw new Exception("Oh no, exception from task 1!!");

});

var task2 = Task.Run(() =>

GoalKicker.com – .NET Framework Notes for Professionals

134

{

Console.WriteLine("Task 2 code starting...");

throw new Exception("Oh no, exception from task 2!!");

});

var tasks = new[] {task1, task2};

Console.WriteLine("Starting tasks..."); while(tasks.All(task => !task.IsCompleted));

foreach(var task in tasks)

{

if(task.IsFaulted) Console.WriteLine("Task failed: " +

task.Exception.InnerExceptions.First().Message);

}

Console.WriteLine("Task 1 status is: " + task1.Status); //Faulted

Console.WriteLine("Task 2 status is: " + task2.Status); //Faulted

Section 42.14: Task: cancelling using CancellationToken

var cancellationTokenSource = new CancellationTokenSource(); var cancellationToken = cancellationTokenSource.Token;

var task = new Task((state) =>

{

int i = 1;

var myCancellationToken = (CancellationToken)state; while(true)

{

Console.Write("{0} ", i++); Thread.Sleep(1000);

myCancellationToken.ThrowIfCancellationRequested();

}

},

cancellationToken: cancellationToken, state: cancellationToken);

Console.WriteLine("Counting to infinity. Press any key to cancel!"); task.Start();

Console.ReadKey();

cancellationTokenSource.Cancel(); try

{

task.Wait();

}

catch(AggregateException ex)

{

ex.Handle(inner => inner is OperationCanceledException);

}

Console.WriteLine($"{Environment.NewLine}You have cancelled! Task status is: {task.Status}");

//Canceled

As an alternative to ThrowIfCancellationRequested, the cancellation request can be detected with

IsCancellationRequested and a OperationCanceledException can be thrown manually:

//New task delegate

GoalKicker.com – .NET Framework Notes for Professionals

135

int i = 1;

var myCancellationToken = (CancellationToken)state; while(!myCancellationToken.IsCancellationRequested)

{

Console.Write("{0} ", i++); Thread.Sleep(1000);

}

Console.WriteLine($"{Environment.NewLine}Ouch, I have been cancelled!!"); throw new OperationCanceledException(myCancellationToken);

Note how the cancellation token is passed to the task constructor in the cancellationToken parameter. This is needed so that the task transitions to the Canceled state, not to the Faulted state, when ThrowIfCancellationRequested is invoked. Also, for the same reason, the cancellation token is explicitly supplied in the constructor of OperationCanceledException in the second case.

Section 42.15: Task.WhenAny

var random = new Random();

IEnumerable<Task<int>> tasks = Enumerable.Range(1, 5).Select(n => Task.Run(async() =>

{

Console.WriteLine("I'm task " + n); await Task.Delay(random.Next(10,1000)); return n;

}));

Task<Task<int>> whenAnyTask = Task.WhenAny(tasks);

Task<int> completedTask = await whenAnyTask;

Console.WriteLine("The winner is: task " + await completedTask);

await Task.WhenAll(tasks); Console.WriteLine("All tasks finished!");

GoalKicker.com – .NET Framework Notes for Professionals

136