Полное руководство по языку программирования С# 14 и платформе .NET 10 / Aсинхронное программирование

Обработка ошибок в асинхронных методах

Начальный ⏱ 4 мин чтения 👁 2 🕓 обновлено 11.08.2026

Обработка ошибок в асинхронных методах, использующих ключевые слова async и await, имеет свои особенности.

Для обработки ошибок выражение await помещается в блок try:


try
{
    await PrintAsync("Hello METANIT.COM");
    await PrintAsync("Hi");
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

async Task PrintAsync(string message)
{
    // если длина строки меньше 3 символов, генерируем исключение
    if (message.Length < 3)
        throw new ArgumentException($"Invalid string length: {message.Length}");
    await Task.Delay(100);     // имитация продолжительной операции
    Console.WriteLine(message);
}

В данном случае асинхронный метод PrintAsync генерирует исключение ArgumentException, если методу передается строка с длиной меньше 3 символов.

Для обработки исключения в методе Main выражение await помещено в блок try. В итоге при выполнении вызова await PrintAsync("Hi") будет сгенерировано исключение, что привет к генерации исключения. Однако программа не остановит аварийно свою работу, а обработает исключение и продолжит дальнейшие вычисления.

Консольный вывод программы:

Hello METANIT.COM
Invalid string length: 2

Следует учитывать, что если асинхронный метод имеет тип void, то в этом случае исключение во вне не передается, соответственно мы не сможем обработать исключение при вызове метода:


try
{
    PrintAsync("Hello METANIT.COM");
    PrintAsync("Hi");       // здесь программа сгенерирует исключение и аварийно остановится
    await Task.Delay(1000); // ждем завершения задач
}
catch (Exception ex)    // исключение НЕ будет обработано
{
    Console.WriteLine(ex.Message);
}

async void PrintAsync(string message)
{
    // если длина строки меньше 3 символов, генерируем исключение
    if (message.Length < 3)
        throw new ArgumentException($"Invalid string length: {message.Length}");
    await Task.Delay(100);     // имитация продолжительной операции
    Console.WriteLine(message);
}

В данном случае, не смотря на то, что асинхронные методы вызываются в блоке try, исключение не будет перехвачено и обработано. В этом один из минусов применения асинхронных void-методов. Правда, в этом случае мы можем определить обработку исключения в самом асинхронном методе:


PrintAsync("Hello METANIT.COM");
PrintAsync("Hi");
await Task.Delay(1000); // ждем завершения задач

async void PrintAsync(string message)
{
    try
    {
        // если длина строки меньше 3 символов, генерируем исключение
        if (message.Length < 3)
            throw new ArgumentException($"Invalid string length: {message.Length}");
        await Task.Delay(100);     // имитация продолжительной операции
        Console.WriteLine(message);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }

}

Исследование исключения

При возникновении ошибки у объекта Task, представляющего асинхронную задачу, в которой произошла ошибка, свойство IsFaulted имеет значение true. Кроме того, свойство Exception объекта Task содержит всю информацию об ошибке. Проинспектируем данное свойство:


var task = PrintAsync("Hi");
try
{
    await task;
}
catch
{
    Console.WriteLine(task.Exception?.InnerException?.Message); // Invalid string length: 2
    Console.WriteLine($"IsFaulted: {task.IsFaulted}");  // IsFaulted: True
    Console.WriteLine($"Status: {task.Status}");        // Status: Faulted
}

async Task PrintAsync(string message)
{
    // если длина строки меньше 3 символов, генерируем исключение
    if (message.Length < 3)
        throw new ArgumentException($"Invalid string length: {message.Length}");
    await Task.Delay(1000);     // имитация продолжительной операции
    Console.WriteLine(message);
}

И если мы передадим в метод строку с длиной меньше 3 символов, то task.IsFaulted будет равно true.

Обработка нескольких исключений. WhenAll

Если мы ожидаем выполнения сразу нескольких задач, например, с помощью Task.WhenAll, то мы можем получить сразу несколько исключений одномоментно для каждой выполняемой задачи. В этом случае мы можем получить все исключения из свойства Exception.InnerExceptions:


// определяем и запускаем задачи
var task1 = PrintAsync("H");
var task2 = PrintAsync("Hi");
var allTasks = Task.WhenAll(task1, task2);
try
{
    await allTasks;
}
catch (Exception ex)
{
    Console.WriteLine($"Exception: {ex.Message}");
    Console.WriteLine($"IsFaulted: {allTasks.IsFaulted}");
    if(allTasks.Exception is not null)
    {
        foreach (var exception in allTasks.Exception.InnerExceptions)
        {
            Console.WriteLine($"InnerException: {exception.Message}");
        }
    }
}

async Task PrintAsync(string message)
{
    // если длина строки меньше 3 символов, генерируем исключение
    if (message.Length < 3)
        throw new ArgumentException($"Invalid string: {message}");
    await Task.Delay(1000);     // имитация продолжительной операции
    Console.WriteLine(message);
}

Здесь в два вызова метода PrintAsync передаются заведомо некорректные значения. Таким образом, при обоих вызовах будет сгенерирована ошибка.

Хотя блок catch через переменную Exception ex будет получать одно перехваченное исключение, но с помощью коллекции Exception.InnerExceptions мы сможем получить информацию обо всех возникших исключениях.

В итоге при выполнении этого метода мы получим следующий консольный вывод:

Exception: Invalid string: H
IsFaulted: True
InnerException: Invalid string: H
InnerException: Invalid string: Hi

Проверь себя

📋 Тест по теме «Обработка ошибок в асинхронных методах» Тест по теме

Практические задания

Лёгкое Ручная проверка Заполните пропуск в коде (1)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

_____
{
    await PrintAsync("Hello METANIT.COM");
    await PrintAsync("Hi");
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

async Task PrintAsync(string message)
{
    // если длина строки меньше 3 символов, генерируем исключение
    if (message.Length < 3)
        throw new ArgumentException($"Invalid string length: {message.Length}");
    await Task.Delay(100);     // имитация продолжительной операции
    Console.WriteLine(message);
}
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (2)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

try
{
    _____("Hello METANIT.COM");
    PrintAsync("Hi");       // здесь программа сгенерирует исключение и аварийно остановится
    await Task.Delay(1000); // ждем завершения задач
}
catch (Exception ex)    // исключение НЕ будет обработано
{
    Console.WriteLine(ex.Message);
}

async void PrintAsync(string message)
{
    // если длина строки меньше 3 символов, генерируем исключение
    if (message.Length < 3)
        throw new ArgumentException($"Invalid string length: {message.Length}");
    await Task.Delay(100);     // имитация продолжительной операции
    Console.WriteLine(message);
}
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (3)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

PrintAsync("Hello _____.COM");
PrintAsync("Hi");
await Task.Delay(1000); // ждем завершения задач

async void PrintAsync(string message)
{
    try
    {
        // если длина строки меньше 3 символов, генерируем исключение
        if (message.Length < 3)
            throw new ArgumentException($"Invalid string length: {message.Length}");
        await Task.Delay(100);     // имитация продолжительной операции
        Console.WriteLine(message);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }

}
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (4)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

var task = PrintAsync("Hi");
try
{
    _____ task;
}
catch
{
    Console.WriteLine(task.Exception?.InnerException?.Message); // Invalid string length: 2
    Console.WriteLine($"IsFaulted: {task.IsFaulted}");  // IsFaulted: True
    Console.WriteLine($"Status: {task.Status}");        // Status: Faulted
}

async Task PrintAsync(string message)
{
    // если длина строки меньше 3 символов, генерируем исключение
    if (message.Length < 3)
        throw new ArgumentException($"Invalid string length: {message.Length}");
    await Task.Delay(1000);     // имитация продолжительной операции
    Console.WriteLine(message);
}
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (5)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

// определяем и запускаем задачи
var task1 = PrintAsync("H");
var task2 = PrintAsync("Hi");
var _____ = Task.WhenAll(task1, task2);
try
{
    await allTasks;
}
catch (Exception ex)
{
    Console.WriteLine($"Exception: {ex.Message}");
    Console.WriteLine($"IsFaulted: {allTasks.IsFaulted}");
    if(allTasks.Exception is not null)
    {
        foreach (var exception in allTasks.Exception.InnerExceptions)
        {
            Console.WriteLine($"InnerException: {exception.Message}");
        }
    }
}

async Task PrintAsync(string message)
{
    // если длина строки меньше 3 символов, генерируем исключение
    if (message.Length < 3)
        throw new ArgumentException($"Invalid string: {message}");
    await Task.Delay(1000);     // имитация продолжительной операции
    Console.WriteLine(message);
}
Войдите, чтобы отправить решение
Среднее Ручная проверка Восстановите код по памяти (1)
+20 XP

В этом фрагменте кода урока пропущены два ключевых элемента. Впишите оба пропущенных значения через запятую в порядке появления (например: x, 5).

try
{
    await PrintAsync("Hello METANIT.COM");
    await PrintAsync("Hi");
}
catch (Exception ex)
{
    _____.WriteLine(ex.Message);
}

async Task PrintAsync(string message)
{
    // если длина строки меньше _____ символов, генерируем исключение
    if (message.Length < 3)
        throw new ArgumentException($"Invalid string length: {message.Length}");
    await Task.Delay(100);     // имитация продолжительной операции
    Console.WriteLine(message);
}
Войдите, чтобы отправить решение
Среднее Ручная проверка Восстановите код по памяти (2)
+20 XP

В этом фрагменте кода урока пропущены два ключевых элемента. Впишите оба пропущенных значения через запятую в порядке появления (например: x, 5).

try
{
    PrintAsync("Hello METANIT.COM");
    PrintAsync("Hi");       // здесь программа сгенерирует исключение и аварийно остановится
    await Task.Delay(1000); // ждем завершения задач
}
catch (Exception ex)    // исключение НЕ будет обработано
{
    Console.WriteLine(ex.Message);
}

_____ void PrintAsync(string message)
{
    // если длина строки меньше 3 символов, генерируем исключение
    if (message.Length < 3)
        _____ new ArgumentException($"Invalid string length: {message.Length}");
    await Task.Delay(100);     // имитация продолжительной операции
    Console.WriteLine(message);
}
Войдите, чтобы отправить решение
Сложное Ручная проверка Объясните и модифицируйте пример из урока «Обработка ошибок в асинхронных методах»
+30 XP

Опишите своими словами, что делает приведённый пример кода из урока «Обработка ошибок в асинхронных методах», и предложите одно осмысленное изменение (например, другое входное значение или дополнительное условие). Приведите итоговый код.

try
{
    await PrintAsync("Hello METANIT.COM");
    await PrintAsync("Hi");
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

async Task PrintAsync(string message)
{
    // если длина строки меньше 3 символов, генерируем исключение
    if (message.Length < 3)
        throw new ArgumentException($"Invalid string length: {message.Length}");
    await Task.Delay(100);     // имитация продолжительной операции
    Console.WriteLine(message);
}
Войдите, чтобы отправить решение
Сложное Ручная проверка Найдите потенциальную проблему в коде урока «Обработка ошибок в асинхронных методах»
+30 XP

Изучите приведённый фрагмент кода и опишите, при каких входных данных или условиях он может сработать не так, как ожидается (граничный случай, отсутствие проверки и т.п.). Предложите исправленный вариант.

try
{
    PrintAsync("Hello METANIT.COM");
    PrintAsync("Hi");       // здесь программа сгенерирует исключение и аварийно остановится
    await Task.Delay(1000); // ждем завершения задач
}
catch (Exception ex)    // исключение НЕ будет обработано
{
    Console.WriteLine(ex.Message);
}

async void PrintAsync(string message)
{
    // если длина строки меньше 3 символов, генерируем исключение
    if (message.Length < 3)
        throw new ArgumentException($"Invalid string length: {message.Length}");
    await Task.Delay(100);     // имитация продолжительной операции
    Console.WriteLine(message);
}
Войдите, чтобы отправить решение
Мини-проект Ручная проверка Мини-проект по теме «Обработка ошибок в асинхронных методах»
+50 XP

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

Войдите, чтобы отправить решение
Домашнее задание Ручная проверка Домашнее задание по теме «Обработка ошибок в асинхронных методах»
+25 XP

Напишите собственную небольшую программу, применяющую материал темы «Обработка ошибок в асинхронных методах». Используйте не менее одной конструкции, показанной в примерах урока. Прикрепите код решения и краткое описание того, что он делает.

Войдите, чтобы отправить решение

Обсуждение (0)

Войдите, чтобы оставить комментарий.