2015-06-06 7 views
6
próbka

Kod:rzucanie wyjątku od Task.Run wyświetla „Nie obsługiwane z kodu użytkownika” Message

using System; 
using System.Threading.Tasks; 

public class Program 
{ 
    public static void Main() 
    { 
     Console.WriteLine("Start"); 
     Foo f = new Foo(); 
     f.FooAsync(); 
    } 

    public class Foo 
    { 
     public async void FooAsync() 
     { 
      try 
      { 
       await Task.Run(() => 
       { 
        Console.WriteLine("Throwing"); 
        throw new Exception(); 
       }); 
      } 
      catch (Exception) 
      { 
       Console.WriteLine("Caught"); 
      } 
     } 
    } 
} 

Powyższy kod podczas uruchamiania z C# skrzypce lub z konsoli na moich wydruków komputerowych:

Start 
Throwing 
Caught 

C# Fiddle Example

Jednakże gdy uruchomię go z Visual Studio (F5 w trybie debugowania), pojawia się następujący komunikat:

Exception Picture

Nie rozumiem, dlaczego otrzymuję komunikat "nie było obsługiwane w kodzie użytkownika" od Visual Studio, chociaż uruchomienie go z konsoli lub skrzypce C# jest w porządku. Czy brakuje mi czegoś oczywistego?

UPDATE

Próbowałem czeka na zadaniu f.FooAsync().Wait(); w Main, ale wyjątek jest nadal zgłaszane jako nieobsługiwany (ten sam komunikat o błędzie).

+1

Kod jest w porządku, ustawienia debuggera są nieprawidłowe. Kliknij link "Otwórz ustawienia wyjątków", odznacz pole wyboru Opuszczone. Jeśli celowo go włączyłeś, kliknij Kontynuuj. –

+0

@HansPassant: Dzięki. Znalazłem także [więcej informacji na temat problemu] (http://stackoverflow.com/a/16925282/906773). –

Odpowiedz

8

Po pierwsze, co jest szczególnego w tym wyjątkiem jest to, że wyrzucane z Task.Run iw tym zakresie, wyjątek naprawdę nie jest obsługiwane przez użytkownika kodu.

Struktura przechwytuje i przechowuje wyjątek w zwróconym zadaniu, aby można było go później obsłużyć, jeśli nie uda się, aby był to wyjątek wyjątku nieobserwowanego (który w .Net 4.0 spowodowałby awarię aplikacji).

Kwestią tutaj jest funkcja "Włącz tylko mój kod" w ustawieniach. Po włączeniu funkcji debugger łamie wyjątki po opuszczeniu kodu użytkownika i wprowadzeniu kodu ramowego, a w tym momencie wyjątek naprawdę nie został obsłużony.

Po wyłączeniu tej funkcji debugger nie złamie tego wyjątku, ponieważ podąży za kodem do struktury i zobaczy wyjątek obsługiwany i przechowywany w zadaniu. Wyjątek zostanie ponownie zgłoszony po wykonaniu zadania i będzie obsługiwany przez twój kod.


Ponieważ manipulacja że rzeczywiście liczy się jeden wykonywana przez ramy, jest to jeszcze prostsze przykład:

public static void Main() 
{ 
    Task.Run(() => 
    { 
     throw new Exception(); 
    }); 
    Console.ReadLine(); 
} 

Z „Włącz Just My Code” włączył debugger złamie na wyjątek, bez niego debugger nie będzie.

+1

Zgadzam się, że jest to poprawna odpowiedź. –