Чтение онлайн

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

new CancellationTokenSource;

do

{

Console.WriteLine("Start any key to start processing");

// Нажмите любую клавишу, чтобы начать обработку

Console.ReadKey;

Console.WriteLine("Processing");

Task.Factory.StartNew(ProcessIntData);

Console.Write("Enter Q to quit: ");

// Введите Q для выхода:

string answer = Console.ReadLine;

//
Желает ли пользователь выйти?

if (answer.Equals("Q",

StringComparison.OrdinalIgnoreCase))

{

_cancelToken.Cancel;

break;

}

}

while (true);

Console.ReadLine;

Теперь запрос PLINQ необходимо информировать о том, что он должен ожидать входящего запроса на отмену выполнения, добавив в цепочку вызов расширяющего метода

WithCancellation
с передачей ему маркера отмены. Кроме того, этот запрос PLINQ понадобится поместить в подходящий блок
try/catch
и обработать возможные исключения. Финальная версия метода
ProcessInData
выглядит следующим образом:

void ProcessIntData

{

// Получить очень большой массив целых чисел.

int[] source = Enumerable.Range(1, 10_000_000).ToArray;

// Найти числа, для которых истинно условие num % 3 == 0,

// и возвратить их в убывающем порядке.

int[] modThreeIsZero = null;

try

{

modThreeIsZero =

(from num in source.AsParallel.WithCancellation(_cancelToken.Token)

where num % 3 == 0

orderby num descending

select num).ToArray;

Console.WriteLine;

// Вывести количество найденных чисел.

Console.WriteLine($"Found {modThreeIsZero.Count} numbers

that match query!");

}

catch (OperationCanceledException ex)

{

Console.WriteLine(ex.Message);

}

}

Во время выполнения метода

ProcessIntData
понадобится нажать <Q> и быстро произвести ввод, чтобы увидеть сообщение от маркера отмены.

Асинхронные вызовы с помощью async/await

В этой довольно длинной главе было представлено много материала в сжатом виде. Конечно, построение, отладка и понимание сложных многопоточных приложений требует прикладывания усилий в любой инфраструктуре. Хотя TPL, PLINQ и тип делегата могут до некоторой степени упростить решение (особенно по сравнению с другими платформами и языками), разработчики по-прежнему должны хорошо знать детали разнообразных расширенных приемов.

С выходом версии .NET 4.5 в языке программирования C# появились два новых ключевых слова, которые дополнительно упрощают процесс написания асинхронного кода. По

контрасту со всеми примерами, показанными ранее в главе, когда применяются ключевые слова
async
и
await
, компилятор будет самостоятельно генерировать большой объем кода, связанного с потоками, с использованием многочисленных членов из пространств имен
System.Threading
и
System.Threading.Tasks
.

Знакомство с ключевыми словами async и await языка C# (обновление в версиях 7.1, 9.0)

Ключевое слово

async
языка C# применяется для указания на то, что метод, лямбда-выражение или анонимный метод должен вызываться в асинхронной манере автоматически. Да, это правда. Благодаря простой пометке метода модификатором
async
среда .NET Core Runtime будет создавать новый поток выполнения для обработки текущей задачи. Более того, при вызове метода
async
ключевое слово
await
будет автоматически приостанавливать текущий поток до тех пор, пока задача не завершится, давая возможность вызывающему потоку продолжить свою работу.

В целях иллюстрации создайте новый проект консольного приложения по имени

FunWithCSharpAsync
и импортируйте в файл
Program.cs
пространства имен
System.Threading
,
System.Threading.Task
и
System.Collections.Generic
. Добавьте метод
DoWork
, который заставляет вызывающий поток ожидать пять секунд. Ниже показан код:

using System;

using System.Collections.Generic;

using System.Threading;

using System.Threading.Tasks;

Console.WriteLine(" Fun With Async ===>");

Console.WriteLine(DoWork);

Console.WriteLine("Completed");

Console.ReadLine;

static string DoWork

{

Thread.Sleep(5_000);

return "Done with work!";

}

Вам известно, что после запуска программы придется ожидать пять секунд, прежде чем сможет произойти что-то еще. В случае графического приложения весь пользовательский интерфейс был бы заблокирован до тех пор, пока работа не завершится.

Если бы мы решили прибегнуть к одному из описанных ранее приемов, чтобы сделать приложение более отзывчивым, тогда пришлось бы немало потрудиться. Тем не менее, начиная с версии .NET 4.5, можно написать следующий код С#:

...

string message = await DoWorkAsync;

Console.WriteLine(message);

...

static string DoWork

{

Thread.Sleep(5_000);

return "Done with work!";

}

static async Task<string> DoWorkAsync

{

return await Task.Run( =>

Поделиться с друзьями: