2012-01-08 36 views
8

我很熟悉這樣的事實:在線程中拋出的異常通常無法在另一個線程中捕獲。 但是,如何將錯誤傳輸到主線程?如何將異常明確地傳遞給c中的主線程#

public static void Main() 
{ 
    new Thread (Go).Start(); 
} 

static void Go() 
{ 
    try 
    { 
    // ... 
    throw null; // The NullReferenceException will get caught below 
    // ... 
    } 
    catch (Exception ex) 
    { 
    // Typically log the exception, and/or signal another thread 
    // that we've come unstuck 
    // ... 
    } 
} 

回答

6

如果您在使用.NET 4中有更好的方法與Tasks要做到這一點,但假設你需要使用Threads ...

如果你的例子是一個控制檯應用程序,然後在你的主要方法將退出,可能在Go開始執行之前。所以當引發異常時,你的「主線程」可能不存在。要停止這一點,你需要一些同步。

像這樣的東西應該做的:

static Exception _ThreadException = null; 

public static void Main() 
{ 
    var t = new Thread (Go); 
    t.Start(); 

    // this blocks this thread until the worker thread completes 
    t.Join(); 

    // now see if there was an exception 
    if (_ThreadException != null) HandleException(_ThreadException); 
} 

static void HandleException(Exception ex) 
{ 
    // this will be run on the main thread 
} 

static void Go() 
{ 
    try 
    { 
     // ... 
     throw null; // The NullReferenceException will get caught below 
     // ... 
    } 
    catch (Exception ex) 
    { 
     _ThreadException = ex; 
    } 
} 

如果這是一個用戶界面的應用程序,事情更容易一些。您需要將一些對UI線程的引用傳遞給Go方法,以便知道發送異常的位置。最好的辦法是通過UI線程的SynchronizationContext

像這樣的工作:

public static void Main() 
{ 
    var ui = SynchronizationContext.Current; 
    new Thread (() => Go(ui)).Start(); 
} 

static void HandleException(Exception ex) 
{ 
    // this will be run on the UI thread 
} 

static void Go(SynchronizationContext ui) 
{ 
    try 
    { 
     // ... 
     throw null; // The NullReferenceException will get caught below 
     // ... 
    } 
    catch (Exception ex) 
    { 
     ui.Send(state => HandleException(ex), null); 
    } 
} 
0

我假設你所謂的「主線程」應該輪詢或等待異常。這可以通過隊列和信號完成。

catch(Exception ex) 
{ 
    lock(queueLock) 
    { 
     queue.Enqueue(ex) 
     semaphore.Release(); 
    } 

} 

在您的主線程中,您可以輪詢或等待信號量。

2

這是一個非常古老的線程,但我有一個原始的方法來解決這個問題,所以我會把我的解決方案放在這裏。

我的主要目標是在子線程得到異常的時候,主線程會被異常中斷,而不是像其他答案中提出的監視或等待。正如在其他線程中所說的那樣,我們不能用傳統的方法來做到這點,但是我們可以從另一個線程向主線程發送中斷。

向主線程發送中斷會在主線程上產生ThreadInterruptedException。因此,在主線程中捕獲它並檢查由其他線程引發的任何標誌都會執行異常詳細信息傳輸。

下面是一個小例子,(你可以打破它的類和做更好的設計後)

static void Main(string[] args) 
    { 


     // initialize the second thread *************************** 
     Exception exFromThread = null; 

     Thread thread = new Thread((mainThread) => 
     { 
      Thread.Sleep(1000); 
      exFromThread = new Exception("Exception from other thread"); 
      ((Thread)mainThread).Interrupt(); // makes the main thread get exception 
     }); 

     thread.Start(Thread.CurrentThread); 
     // ******************************************************** 

     try 
     { 
      // This loop represents your main thread logic 
      for (int i = 0; true; i++) 
      { 
       Thread.Sleep(500); 
       Console.WriteLine("main thread logic: " + i); 
      } 
     } 
     catch (ThreadInterruptedException ex) 
     { 
      Console.WriteLine("Thread have been interrupted"); 
      Console.WriteLine(exFromThread.Message); 
     } 

     Console.WriteLine("Press any key.."); 

     Console.ReadLine(); 
    } 
相關問題