2012-07-04 38 views
2

我想在線程A中捕獲異常,然後將異常對象傳遞給線程B,並將其從線程B拋出。是否安全?安全拋出在另一個線程上創建的異常C#

線程A

try { 
    // Code that throws exceptions 
} catch (Exception e) { 
    sendToOtherThread(e); 
} 

線程B

Exception e = receiveException(); 
throw e; 

編輯

爲了清楚:我瞭解線程的作品,我應該如何通過從一個對象引用線程到另一個。問題更多的是從一個沒有創建它的線程拋出一個異常對象是安全的,還是有類本身或者.NET處理它的方式的問題。

+0

是的,但(可能)很沒用,因爲你不能重新拋出,所以你會覆蓋原來的堆棧跟蹤。如果這不是你想要的,你必須包裝異常並拋出新的異常。 –

+0

我很好奇你的'sendToOtherThread'和'receiveException'的實現。 –

+0

讓我們只是說這兩個方法按原樣傳遞對象引用。所以兩個線程中的e都指向同一個對象。 –

回答

1

可以重新拋出從另一個線程接收(例如,在一個BackgroundWorker的RunWorkerCompleted事件處理程序)的例外,但它會更通常把它包起來的另一個例外,以保留堆跟蹤:

private void backgroundWorker1_RunWorkerCompleted(
    object sender, RunWorkerCompletedEventArgs e) 
{ 
    // First, handle the case where an exception was thrown. 
    if (e.Error != null) 
    { 
     throw new SomeException("... message ...", e.Error); 
    } 
    ... 
} 
0

你需要改變這一點:

在線程B

Exception e = receiveException(); 
throw new Exception("Write something here, for example: 'Received from other thread'", e); // so you keep the stack trace 

但我會留意的注意事項(我不能完全肯定這是100%安全的)。

+0

感謝您的重新包裝建議。但是這個問題仍然沒有得到答案: -/ –

+0

這是一個很好的主意來包裝你的異常,以跟蹤拋出異常的原始線程,但是正如OP所說,它不是對問題的回答 – AaA

0

它應該是安全的,但很可能會終止線程B.

您的解決方案只取決於你如何從線程A通過你的異常對象線程B. 如果你把它放在一個共享資源您需要鎖定並釋放該特定的共享資源。除此之外,您的代碼沒有任何不安全因素。

只要你沒有訪問線程中的任何共享資源,其他的一切都應該是安全的。

0

Exception是一個類,因此是一個標準的引用類型,如果你想在線程之間傳遞它(這聽起來有點奇怪),你需要確保沒有其他人試圖修改實例(特別是如果你創建自己的mutable異常類型)。

解決方案A
你可以做一個生產者 - 消費者拉模型

BlockingCollection<Exception> bc = new BlockingCollection<Exception>(); 

// thread A - Producer 
try 
{ 
    ... 
} 
catch(Exception ex) 
{ 
    bc.Add(ex); 
} 


//thread B - Consumer 
try 
{ 
    // Consume bc 
    while (true) 
    { 
     var ex = bc.Take(); 
     //thread sleep 
    } 
} 
catch (InvalidOperationException) 
{ 
    // IOE means that Take() 
    // was called on a completed collection and no 
    // No more exceptions, restart checking  
} 

溶液B
但可能是一個更好的想法是不使用拉模型,在此它可能會浪費資源,而是使用線程安全可觀察集合的推式模型。

相關問題