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

ЖАНРЫ

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

Локальные функции (нововведение в версии 7.0)

Локальные функции были представлены в главе 4 и использовались в главе 8 с итераторами. Они также могут оказаться полезными для асинхронных методов. Чтобы продемонстрировать преимущество, сначала нужно взглянуть на проблему. Добавьте новый метод по имени

MethodWithProblems
со следующим кодом:

static async Task MethodWithProblems(int firstParam, int secondParam)

{

Console.WriteLine("Enter");

await Task.Run( =>

{

//
Вызвать длительно выполняющийся метод

Thread.Sleep(4_000);

Console.WriteLine("First Complete");

// Вызвать еще один длительно выполняющийся метод, который терпит

// неудачу из-за того, что значение второго параметра выходит

// за пределы допустимого диапазона.

Console.WriteLine("Something bad happened");

});

}

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

static async Task MethodWithProblemsFixed(int firstParam, int secondParam)

{

Console.WriteLine("Enter");

if (secondParam < 0)

{

Console.WriteLine("Bad data");

return;

}

await actualImplementation;

async Task actualImplementation

{

await Task.Run( =>

{

// Вызвать длительно выполняющийся метод

Thread.Sleep(4_000);

Console.WriteLine("First Complete");

// Вызвать еще один длительно выполняющийся метод, который терпит

// неудачу из-за того, что значение второго параметра выходит

// за пределы допустимого диапазона.

Console.WriteLine("Something bad happened");

});

}

}

Отмена операций async/await

Шаблон

async/await
также допускает отмену, которая реализуется намного проще, чем с методом
Parallel.ForEach
. Для демонстрации будет применяться тот же самый проект приложения WPF, рассмотренный ранее в главе. Вы можете либо повторно использовать этот проект, либо создать в решении новый проект приложения WPF (.NET Core) и добавить к нему пакет
System.Drawing.Common
с помощью следующих команд CLI:

dotnet new wpf -lang c# -n PictureHandlerWithAsyncAwait

– o .\PictureHandlerWithAsyncAwait -f net5.0

dotnet sln .\Chapter15_AllProjects.sln add .\PictureHandlerWithAsyncAwait

dotnet add PictureHandlerWithAsyncAwait package System.Drawing.Common

Если

вы работаете в Visual Studio, тогда щелкните правой кнопкой мыши на имени решения в окне Solution Explorer, выберите в контекстном меню пункт Add?Project (Добавить?Проект) и назначьте ему имя
PictureHandlerWithAsyncAwait
. Сделайте новый проект стартовым, щелкнув правой кнопкой мыши на его имени и выбрав в контекстном меню пункт Set as Startup Project (Установить как стартовый проект). Добавьте NuGet-пакет
System.Drawing.Common
:

dotnet add PictureHandlerWithAsyncAwait package System.Drawing.Common

Приведите разметку XAML в соответствие с предыдущим проектом приложения WPF, но с заголовком

Picture Handler with Async/Await
.

Удостоверьтесь, что в файле

MainWindow.xaml.cs
присутствуют показанные ниже операторы
using
:

using System;

using System.IO;

using System.Threading;

using System.Threading.Tasks;

using System.Windows;

using System.Drawing;

Затем добавьте переменную уровня класса для объекта

CancellationToken
и обработчик событий для кнопки Cancel:

private CancellationTokenSource _cancelToken = null;

private void cmdCancel_Click(object sender, EventArgs e)

{

_cancelToken.Cancel;

}

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

Parallel.ForEach
, и сигнатуры методов принимают в качестве параметра объект
CancellationToken
. Введите следующий код:

private async void cmdProcess_Click(object sender, EventArgs e)

{

_cancelToken = new CancellationTokenSource;

var basePath = Directory.GetCurrentDirectory;

var pictureDirectory =

Path.Combine(basePath, "TestPictures");

var outputDirectory =

Path.Combine(basePath, "ModifiedPictures");

// Удалить любые существующие файлы

if (Directory.Exists(outputDirectory))

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