Язык программирования C#9 и платформа .NET5
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. Для демонстрации будет применяться тот же самый проект приложения WPF, рассмотренный ранее в главе. Вы можете либо повторно использовать этот проект, либо создать в решении новый проект приложения WPF (.NET Core) и добавить к нему пакетParallel.ForEach()с помощью следующих команд CLI:System.Drawing.Commondotnet new wpf -lang c# -n PictureHandlerWithAsyncAwait-o .\PictureHandlerWithAsyncAwait -f net5.0dotnet sln .\Chapter15_AllProjects.sln add .\PictureHandlerWithAsyncAwaitdotnet add PictureHandlerWithAsyncAwait package System.Drawing.CommonЕсли вы работаете в Visual Studio, тогда щелкните правой кнопкой мыши на имени решения в окне Solution Explorer, выберите в контекстном меню пункт Add►Project (Добавить►Проект) и назначьте ему имя
. Сделайте новый проект стартовым, щелкнув правой кнопкой мыши на его имени и выбрав в контекстном меню пункт Set as Startup Project (Установить как стартовый проект). Добавьте NuGet-пакетPictureHandlerWithAsyncAwait:System.Drawing.Commondotnet add PictureHandlerWithAsyncAwait package System.Drawing.CommonПриведите разметку XAML в соответствие с предыдущим проектом приложения WPF, но с заголовком
.Picture Handler with Async/AwaitУдостоверьтесь, что в файле
присутствуют показанные ниже операторыMainWindow.xaml.cs:usingusing System;using System.IO;using System.Threading;using System.Threading.Tasks;using System.Windows;using System.Drawing;Затем добавьте переменную уровня класса для объекта
и обработчик событий для кнопки Cancel:CancellationTokenprivate CancellationTokenSource _cancelToken = null;private void cmdCancel_Click(object sender, EventArgs e){_cancelToken.Cancel();}Процесс здесь такой же, как в предыдущем примере: получение каталога с файлами изображений, создание выходного каталога, получение файлов, поворот изображений в файлах и сохранение их в выходном каталоге. В новой версии для выполнения работы будут применяться асинхронные методы, а не
, и сигнатуры методов принимают в качестве параметра объектParallel.ForEach(). Введите следующий код:CancellationTokenprivate async void cmdProcess_Click(object sender, EventArgs e){_cancelToken = new CancellationTokenSource();var basePath = Directory.GetCurrentDirectory();var pictureDirectory =Path.Combine(basePath, "TestPictures");