Przechwytywanie wyjątków w async await

Wyjątek wewnątrz wyrażenia lambda

Jeśli powstanie wyjątek wewnątrz wyrażania lambda, która jest wywoływana wewnątrz nowego obiektu Task, wówczas nie jest możliwe przechwycenie tego wyjątku na zewnątrz, poza tym wyrażeniem lambda. Poniżej przykład takiej sytuacji.

Definiujemy metodę, która w obiekcie Task asynchronicznie odpala operację, która generuje wyjątek.

private static Task DoDangerousThingInNewTask()
{
    return Task<int>.Factory.StartNew(() =>
    {
        SimpulateLongRunningAsync();
        throw new Exception("the intentional exception");
    });
}

W kolejnej metodzie wywołujemy tę metodę DoDangerousThingInNewTask i próbujemy przechwycić wyjątek.

private static async void DoSafeThingAsync()
{
    try
    {
        await DoDangerousThingInNewTask();
        Console.WriteLine("next calculations and logic");
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }
}

Niestety, powyższy kod nie wykona się poprawnie. Wyjątek, który powstał w metodzie DoDangerousThingInNewTask nie zostanie przechwycony w klauzurze catch w metodzie DoSafeThingAsync.

Wyjątek wewnątrz metody z modyfikatorem async

Inaczej jest w przypadku metod z modyfikatorem async. Jeśli w metodzie z modyfikatorem async, zwracającej obiekt typu Task, wystąpi nieobsłużony wyjątek, wówczas jest on propagowany wyżej do metody wywołującej tę metodę, Zatem, na zewnątrz tej metody z modyfikatorem async, można użyć konstrukcji try{}catch{} w celu przechwycenia wyjątku.

Definiujemy metodę z modyfikatorem async, w której generujemy wyjątek.

private static async Task DoDangerousThingAsync()
{
    await SimpulateLongRunningAsync();
    throw new Exception("the intentional exception");
}

W kolejnej metodzie analogicznie jak poprzednio wywołujemy metodę DoDangerousThingAsync i przechwytujemy wyjątek.

private static async void DoSafeThingAsync()
{
    try
    {
        await DoDangerousThingAsync();
        Console.WriteLine("next calculations and logic");
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }
}

Tutaj kod wykona się tak, jak byśmy tego oczekiwali. Wyjątek zostanie przechwycony w klauzurze catch w metodzie DoSafeThingAsync.

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj /  Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj /  Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj /  Zmień )

Połączenie z %s