2013-08-06 7 views
39

Po dołączeniu debuggera do procesu .NET (zwykle) zatrzymuje się po zgłoszeniu nieobsługiwanego wyjątku.Program debugujący nie łamie/nie zatrzymuje się w przypadku wyjątków w metodzie asynchronicznej

Jednak to nie działa, gdy jesteś w metodzie async.

Scenariusze próbowałem wcześniej wymienione są w poniższym kodzie:

class Program 
{ 
    static void Main() 
    { 
     // Debugger stopps correctly 
     Task.Run(() => SyncOp()); 

     // Debugger doesn't stop 
     Task.Run(async() => SyncOp()); 

     // Debugger doesn't stop 
     Task.Run((Func<Task>)AsyncTaskOp); 

     // Debugger stops on "Wait()" with "AggregateException" 
     Task.Run(() => AsyncTaskOp().Wait()); 

     // Throws "Exceptions was unhandled by user code" on "await" 
     Task.Run(() => AsyncVoidOp()); 

     Thread.Sleep(2000); 
    } 

    static void SyncOp() 
    { 
     throw new Exception("Exception in sync method"); 
    } 

    async static void AsyncVoidOp() 
    { 
     await AsyncTaskOp(); 
    } 

    async static Task AsyncTaskOp() 
    { 
     await Task.Delay(300); 
     throw new Exception("Exception in async method"); 
    } 
} 

Am I czegoś brakuje? Jak mogę sprawić, aby debugger przerwał/zatrzymał się na wyjątku w AsyncTaskOp()?

+0

Czy kiedykolwiek rozwiązać ten problem? –

+0

@RichardSzalay Nie, niestety nie. Sądzę, że po prostu przyzwyczaiłem się do tego. –

Odpowiedz

25

W menu Debug wybierz Exceptions.... W oknie dialogowym Wyjątki, obok linii Common Language Runtime Exceptions sprawdź pole Thrown.

+14

Ok, ja to wiedziałem. Ale wtedy debugger włamie się na * wszystkie * wyjątki, nie tylko na nieobsługiwane, prawda? Więc nie jest to dokładnie to, czego szukam. –

+3

@SebastianKrysmanski: Wyjątek jest jednak obsługiwany. Jeśli masz metodę 'async Task', to wyjątek jest przechwytywany przez maszynę stanu' async' i umieszczany w zwracanym 'Task'. –

+10

W Visual Studio 2015, ustawienia wyjątków znajdują się w 'Debugowanie' >>' Windows' >> 'Ustawienia wyjątków' (Ctrl + Alt + E) –

-2

Zawinęłam anonimowego delegata w próbie/catch wewnątrz Task.Run(() =>.

Task.Run(() => 
{ 
    try 
    { 
      SyncOp()); 
    } 
    catch (Exception ex) 
    { 
      throw; // <--- Put your debugger break point here. 
        // You can also add the exception to a common collection of exceptions found inside the threads so you can weed through them for logging 
    } 

}); 
+2

Nie pomaga, ponieważ wtedy debugger zostałby złamany w miejscu, w którym wystąpił wyjątek jest * złapany * - nie tam, gdzie jest * wyrzucony *. –

3

Chciałbym usłyszeć, jeśli ktoś dowiedział się, jak obejść ten problem? Być może ustawienie w najnowszym visual studio ...?

Paskudny ale wykonalne rozwiązanie (w moim przypadku) było rzucać własne zwyczaj wyjątek i następnie modyfikować Stephen Cleary za odpowiedź:

w menu Debug wybierz wyjątkami (Możesz użyć tej klawiatury skrót Kontrola + Alt + E) ... W oknie dialogowym Wyjątki obok wyjątków Common Language Runtime linia sprawdzić rzucony pudełko.

być bardziej szczegółowe tj dodać niestandardową wyjątek na liście, a następnie zaznaczyć swoją „rzucony” okno.

Np:

async static Task AsyncTaskOp() 
{ 
    await Task.Delay(300); 
    throw new MyCustomException("Exception in async method"); 
} 
+2

Co się stanie, jeśli 'Task.Delay()' zgłasza inny wyjątek? –

+0

Thomas, właśnie rozwijałem się na przykładzie oryginalnego plakatu. Odejście od logiki, * wszystko * może zawieść - co jest prawdą, ale musimy odpowiedzieć w kontekście, ... abyśmy mogli kręcić w kółko na zawsze ... Moja odpowiedź brzmi: w kontekście zatrzymania debuggera w pożądanym wskaż w kodzie, w którym możesz następnie zobaczyć, jakie są wartości zmiennych lokalnych i potencjalnie, co jest przyczyną wyjątku. Nie można tego łatwo osiągnąć, jeśli wyjątek zostanie odrzucony poza Zadanie (zgodnie z OP), ponieważ może stać się koszmarem do debugowania. – Jimbob

Powiązane problemy