2013-07-17 10 views
11

nie próbuje złapać zewnątrz: await Task.Run(() => sens albo po prostu z nich korzystać jedynie wewnątrz czekająSpróbuj złapać na zewnątrz: czekają Task.Run (()

private async void Test() 
{ 
    try 
    { 
     await Task.Run(() => 
     { 
      try 
      { 
        DoingSomething(); 
      } 
      catch (Exception ex) 
      { 
        log.Error(ex.Message); 
      } 
     }); 
     } 
     catch (Exception ex) 
     { 
      log.Error(ex.Message); 
     } 
} 
+1

To całkowicie zależy od sposobu radzenia sobie z błędem. – SLaks

+8

Ponadto, nigdy nie pisz "async void". – SLaks

+0

Mam zamiar złapać wszystkie błędy od czasu do czasu, ale czy bezpieczniej jest też wypróbować Wypróbuj Catch na zewnątrz? – as74

Odpowiedz

12

Jeśli uchwyt Exception wewnątrz delegata (w przypadku tylko dla zalogowaniu celu), await nie podniesie wyjątek w normalnych okolicznościach. To powinno być w porządku.

private async Task Test() 
{ 
     await Task.Run(() => 
     { 
      try 
      { 
        DoingSomething(); 
      } 
      catch (Exception ex) 
      { 
        log.Error(ex.Message); 
      } 
     }); 

} 

Jednakże, ponieważ jesteś await ing na Task najprawdopodobniej nie będzie jakiś DoSomethingElse w metodzie Test, które mogłyby mieć wpływ na wynik Task - w tym przypadku również warto mieć a try/catch około await.

private async Task Test() 
{ 
    try 
    { 
     await Task.Run(() => 
     { 
      try 
      { 
        DoingSomething(); 
      } 
      catch (SomeSpecialException spex) 
      { 
        // it is OK to have this exception 
        log.Error(ex.Message); 
      } 
     }); 

     DoSomethingElse(); // does not run when unexpected exception occurs. 
     } 
     catch (Exception ex) 
     { 
      // Here we are also running on captured SynchronizationContext 
      // So, can update UI to show error .... 
     } 
} 
+0

Próbowałem tego w aplikacji konsolowej i wprowadziłem przerwę w haczyku, nie było to w głównym wątku, ponownie rzucam i nic się nie dzieje. Chcę, aby główny wątek otrzymał wyjątek. jak mogę to zrobić? – pogorman

+0

Aplikacja @pogorman Console nie ma kontekstu synchronizacji, więc kod po oczekiwaniu może zostać uruchomiony na dowolnym wątku. Jeśli twoja rzeczywista aplikacja to WPF lub WinForm, wyjątek zostanie podniesiony z powrotem na główny wątek – YK1

+0

jaka jest najlepsza strategia dla aplikacji konsolowej? Jeśli w tle wystąpi wyjątek, chcę, aby aplikacja mocno się zawiesiła, aby błędy zostały połknięte cicho. Dzięki. – pogorman

8

Jeśli delegat przechodzą do Task.Run podnosi wyjątek , wtedy można złapać go na zewnątrz Task.Run kiedy await wracającego zadanie.

nie należy myśleć await jakby był to blok. nie ma czegoś takiego jak „wewnątrz czekają”. Zamiast myśleć await jako operator, który przyjmuje jeden argument (w tym przypadku: Task zwrócony przez Task.Run). Task.Run będzie przechwytywać wyjątki od swojego delegata i umieszczać je na zwróconym Task; await będzie następnie propagować ten wyjątek.

+3

Możesz wychwycić wyjątek tylko na zewnątrz, jeśli delegat jest oznaczony jako async ( , nawet jeśli nie ma oczekiwanego oświadczenia w delegacie) Task.Run (async() => {throw new Exception ("msg");}); ' – Arvis

+2

@Arvis: Nie, możesz go złapać bez' async' wewnątrz 'Task.Run'. –

+1

Po prostu wpadłem na tę samą sytuację. Nie mogłem złapać 'SQLException' poza' Task.Run', chyba że dodałem słowo kluczowe 'async' do mojej lambda – NonSecwitter

1

Możesz również dodać catch catch do kodu zewnętrznego. Kompilator wykona sekcję catch, gdy wystąpi wyjątek podczas połączenia asynchronicznego. Oto więcej szczegółów dlaczego trzeba spróbować połowu wokół czekają http://msdn.microsoft.com/en-us/library/vstudio/0yd65esw.aspx Wyjątki spojrzeć w ASYNC Metod