2009-04-22 3 views
13

왜 그런 생각이 들지만, 누군가가 스레드 내부에서 발생 된 예외가 시작된 코드에 의해 결코 잡히지 않는 이유에 대해 잘 파악하고 있는지 묻고 싶습니다. 여기에 내가 무슨 뜻인지 설명하기 매우 간단한 코드입니다 :시도/캐치 및 스레딩

using System; 
using System.Collections.Generic; 
using System.Threading; 

namespace TestCrash 
{ 
    class Program 
    { 
     private static void Crash(object control) 
     { 
      AutoResetEvent are = (AutoResetEvent)(((object[])control)[0]); 
      are.Set(); 
      throw new Exception("Burn baby burn"); 
     } 
     static void Main(string[] args) 
     { 
      try 
      { 
       List<WaitHandle> waitHandles = new List<WaitHandle>(); 
       for (int i = 0; i < 100; i++) 
       { 
        AutoResetEvent are = new AutoResetEvent(false); 
        waitHandles.Add(are); 
        object[] procControl = new object[] { are }; 
        ThreadPool.QueueUserWorkItem(Crash, procControl); 
        WaitHandle.WaitAll(waitHandles.ToArray()); 
       } 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.Message); 
      } 
     } 
    } 
} 

내가 순진은 try/캐치를함으로써 내가 안전 할 것이라고 생각하지만, 나는 그것이 사건이 아니라고 하드 방법을 발견은 (는 충돌입니다 내 서비스 중 하나).

+0

이상한, 지금 막 비슷한 스레드를 시작하려고했습니다. –

+0

확실한 ive는 호출 스레드에 예외를 버블시킵니다. Altho는 ThreadPool을 사용하지 않습니다. just Thread T = 새 스레드 (새 ThreadStart (대리자() {Console.WriteLine ("충돌!"); DoCrashyThingy();}))); T.Start(); – Fusspawn

+0

나는 그것에 대해 쉽게 잘못 될 수있다, 나의 일의 대부분은이 무시 무시한 싱글 스레드 거물이다 .. – Fusspawn

답변

28

일반적으로 새 스레드에서 예외가 throw 될 때까지 원래 스레드가 어디인지는 알 수 없습니다. 예외가 발생하면 스레드가 대기하는 이유는 무엇입니까?

관련 스택을 생각해보십시오. 예외가 발생하면 해당 스택이 적절한 catch 블록에 도달 할 때까지 스택으로 올라갑니다. 새 스레드는 작성 스레드와 완전히 별도의 스택을 가지므로 작성 스레드의 스택에서 catch 블록에 도달하지 않습니다.

편집 : 물론, 생성 스레드 을 수행하도록 시스템을 설계하면 Windows Forms 응용 프로그램의 메시지 루프와 같은 비트가 생길 때까지 기다릴 수 있습니다. 그런 다음 새 스레드가 예외를 catch하고 메시지를 생성 스레드에 보내면 예외를 처리 할 수 ​​있습니다. 그것은 정상적인 설정이 아니기 때문에 - 모두 명시 적으로해야합니다.

+0

고마워, Jon. 나를 혼란스럽게 한 것은 실제로 부모 프로세스에 충돌이 발생한다는 것입니다. 나는 스레드가 적어도 모든 것을 가져 오는 대신 평화롭게 죽어야한다고 생각합니다. –

+0

아니요 - 요점은 예상치 못한 예외가 심각하게 잘못되어 있다는 것을 나타낼 수 있으며 빠르다는 것이 일반적으로 더 좋은 아이디어라는 것입니다. 이것은 .NET 2.0의 새로운 동작입니다. http://msdn.microsoft.com/en-us/library/ms228965.aspx 참조하십시오. –

+0

그래서 스레드 큐에 대기중인 코드 블록은 try/catch 블록 자체에 완전히 포함되어야합니다. 모범 사례가 되겠습니까?나는 그 스레드 중 하나가 문제가 생겨서 그냥 내려오고 싶지 않은 서비스를 가지고 있습니다 ... –

2

특히 여러 스레드가 관련된 경우에는 잘못된 가정을 사용하는 것이 좋습니다.

이겠습니까? 스레드를 시작한 코드에서 예외가 발생 했습니까? 예외가 발생하면 스레드를 시작한 코드가 존재하지 않을 수도 있습니다.

+1

은 제쳐두고, 나는 그것이 생존하기위한 가정이 필요하다는 현실을 무시하기 때문에 그 말을 싫어합니다. 이 말이 말하는 것은 귀하의 가정이 무엇인지 이해하고 그들이 잘못된 위치를 결정하는 것을 의미합니다. –

2

실행중인 스레드가 다른 스레드에서 실행 중이므로 try/catch 문에서 catch되지 않습니다. Try/Catch는 현재 스레드에서만 작동합니다. 당신이해야 할 일은 스레드에 의해 실행되는 함수를 try/catch하고, 충돌이 발생할 때 어떤 일이 일어나는지 관리하는 방법입니다.

2

EventGeneratingThread wrapper을 사용하는 것이 좋습니다. 이렇게하면 스폰 된 프로세스의 스레드에서 발생하는 예외를 포착하고 처리 할 수 ​​있습니다.

나는 배경 노동자를 사용하고

<System.Diagnostics.DebuggerNonUserCodeAttribute()> _ 

하위 당신의 DoWork 전에이 추가

2

시도하고 당신이 가진 그들을 예상대로 내 루프 작업의 모든 시도 캐치.