2010-06-01 21 views
6

Jak wychwycić wyjątek w wątku głównym, jeśli wyjątek wystąpił w wątku dodatkowym?Jak wychwycić wyjątek w głównym wątku, jeśli wyjątek wystąpił w wątku dodatkowym?

fragment kodu dla scenariusza jest podany poniżej:

private void button1_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     Thread th1 = new Thread(new ThreadStart(Test)); 
     th1.Start();    
    } 
    catch (Exception) 
    { 

    } 
} 

void Test() 
{ 
    for (int i = 0; i < 100; i++) 
    { 
     Thread.Sleep(100); 

     if (i == 2) 
      throw new MyException(); 
    } 
} 
+0

Nie możesz. Po pierwsze, do czasu wyrzucenia wyjątku próba ... catch w wątku głównym została już zakończona. –

Odpowiedz

3

Można dodać obsługi Application.ThreadException zdarzenia:

Joe jest prawidłowe. Biorąc pod uwagę powyższe Windows Forms kod byłem zakładając Windows Forms:

To wydarzenie pozwala Twój Windows Forms aplikację do obsługi inaczej nieobsłużonych wyjątków, które występują w Windows Forms wątki. Dołącz obsługę zdarzeń do zdarzenia ThreadException , aby poradzić sobie z tymi wyjątkami, , co sprawi, że Twoja aplikacja stanie się nieznany w stanie . Tam, gdzie to możliwe, wyjątki od powinny być obsługiwane za pomocą bloku obsługi wyjątków strukturalnych .

Zobacz Unexpected Errors in Managed Applications

+1

Myślę, że ta odpowiedź jest błędna. AFAIK (ale nie mam czasu, aby go przetestować), Application.ThreadException obsługuje tylko wyjątki od wątku interfejsu użytkownika (na przykład nieobsługiwany wyjątek w procedurze obsługi zdarzeń dla formantu WinForms). Wyjątki od wątków roboczych mogą być obsługiwane przez procedurę obsługi zdarzenia AppDomain.UnhandledException, ale program obsługi będzie działał w wątku roboczym, a nie w głównym wątku interfejsu użytkownika. Jeśli chcesz obsłużyć wyjątki z wątku roboczego w wątku interfejsu WinForms, najlepszym rozwiązaniem jest użycie elementu BackgroundWorker, jak wskazano w mojej odpowiedzi. – Joe

+0

, który może być kod ASP.NET tak łatwo, jak Windows Forms. Może to być nawet pseudokodek. –

+0

Prawda. Obecnie pracuję nad WinFormami, więc wszystko wygląda jak winFormy! –

2

Użyj BackgroundWorker.

Usługa BackgroundWorker zapewnia infrastrukturę do komunikacji między głównym wątkiem interfejsu użytkownika a wątkiem pracującym w tle, w tym wyjątkami raportowania. To prawie zawsze lepsze rozwiązanie niż uruchomienie wątku z obsługi zdarzenia button_click.

+0

"??????????" - BackgroundWorker zapewnia infrastrukturę do komunikacji między głównym wątkiem UI a wątkiem pracującym w tle, w tym wyjątkami raportowania. Jest prawie zawsze lepszym rozwiązaniem niż uruchamianie wątku z programu obsługi zdarzenia button_click, takiego jak przykład OP. – Joe

+2

na pewno ... więc umieść to w swojej odpowiedzi :). Nie, że referencja jest zła, ale wyjaśnienie jest jeszcze lepsze! – Kiril

0

Możesz także użyć asynchronicznego delegata, aby zapełnić informacje, jeśli niepokoisz się globalnym zalewkowaniem wszystkich wyjątków.

zobaczyć here

To znaczy, pułapki wyjątek w wątku B i użyć Async Delegata do informacji bubble do wątku A. W ten sposób można można szczególnie ukierunkowanych gdy dane z wyjątkiem jest obsługiwane.

0

Jak powiedział @codeka, nie można. Ale jeśli chcesz zrobić coś z interfejsem użytkownika (może być wyświetlany komunikat o błędzie MessageBox dla użytkownika) w bloku catch w wątku dodatkowym, możesz zamknąć to w ten sposób. Lepiej jeśli używasz BackgroundWorker

Invoke(new Action(() => 
{ 
    MessageBox.Show("Message"); 
})); 
1

Należy rozważyć dodawania obsługi wyjątków w metodzie badania i radzić sobie z wyjątkami tam.

Bezpłatny ebook omawia to podejście (i kilka innych). Przewiń w dół do sekcji "Obsługa wyjątków".

0

Można (obecnie & hellip; ta nie była dostępna, gdy pytanie pierwotnie zadawane) używać async i await:

private async void button1_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     await Task.Run(Test); 
    } 
    catch (Exception) 
    { 

    } 
} 

Sposób Task.Run() spowoduje, że metoda Test() być wykonywane w wątku roboczego. Jeśli w tym wątku zostanie zgłoszony nieobsługiwany wyjątek, Task będzie propagować ten wyjątek z powrotem do wątku oczekującego na oświadczeniu await.

Powiązane problemy