2017-06-15 41 views
0

我有一個C#應用程序,它使用CLR調用C++代碼庫(我無法修改)中的功能。處理在C#中的C++線程引發的異常

我的C#應用​​程序初始化C++的東西,然後定期與它交互。

當C++的東西初始化它產生一個線程,然後運行的應用程序的生命週期。

有一些條件,超出我的控制範圍,這可能會導致C++的東西引發異常 - 這是我的應用程序崩潰。我必須強調,崩潰的原因不是由我的應用程序所做的任何事情發起的。

我試過AppDomain.CurrentDomain.UnhandledException路由,但它沒有發現異常。

任何想法?

**簡而言之,C++的東西啓動Direct3D - 如果設備丟失,引發異常。有幾件事情會導致這種情況,但一個很好的例子是用戶鎖定他們的PC(Windows)。

+3

我會忍不住做一個C++/CLI包裝組件可以做這種粘合邏輯。是否調用底層的C++代碼,捕獲任何不受管理的異常,並處理它們或將它們作爲受管異常傳遞。 – Rook

+0

如果C++線程由於未處理的異常而終止,並且沒有託管堆棧幀,那麼這是一個純粹的C++問題。如果您無法以某種方式與該線程交互,將會調用默認的CRT動作,從而終止您的應用。即使你可以處理這個錯誤,你仍然可以處理部分創建的C++對象,如果涉及到靜態的話會讓你無法正確地重新初始化事物。如果圖書館沒有辦法通過例如註冊一些錯誤,重試處理程序,您將需要重新啓動。 –

+0

感謝@AloisKraus - 我不介意處理錯誤,因爲我可以簡單地重新實例化並初始化CLR對象。 – grae22

回答

-2

您應該在不同的AppDomain中執行外部代碼,因此如果外部代碼失敗,您的應用程序將繼續運行,儘管其他域名終止。

public static class NewAppDomain 
{ 
    public static void Execute(Action action) 
    { 
     AppDomain domain = null; 

     try 
     { 
      domain = AppDomain.CreateDomain("New App Domain: " + Guid.NewGuid()); 

      var domainDelegate = (AppDomainDelegate)domain.CreateInstanceAndUnwrap(
       typeof(AppDomainDelegate).Assembly.FullName, 
       typeof(AppDomainDelegate).FullName); 

      domainDelegate.Execute(action); 
     } 
     finally 
     { 
      if (domain != null) 
       AppDomain.Unload(domain); 
     } 
    } 

    private class AppDomainDelegate : MarshalByRefObject 
    { 
     public void Execute(Action action) 
     { 
      action(); 
     } 
    } 
} 

然後,你可以使用這個類

NewAppDomain.Execute(() => 
{ 
    //Here call external code 
    Console.WriteLine("Hello World"); 
}); 

這裏更多新的AppDomain執行外部代碼:https://malvinly.com/2012/04/08/executing-code-in-a-new-application-domain/

+0

你是說我應該在你的「調用外部代碼」方法中做我的C++初始化調用?當該方法存在時,結果對象是否不會被丟棄? – grae22

+0

@ grae22使用這種方法,您可以確定,如果外部通話出現故障,您的應用程序將繼續運行。你不會提供關於你的應用程序的更多細節,因此假設你需要調用一個外部函數並返回,這就是要走的路。如果您需要保持外部對象的活性,那麼您需要稍微不同的方法,但在新的AppDomain中明確運行它是處理失敗的外部代碼以殺死您的應用程序的方式。 – Oscar

+0

謝謝@Oscar,我正在調整您的解決方案。 – grae22