2017-03-04 76 views
0

我正在調用後臺線程中的DLL函數之一。如何在c中的線程中處理dll函數調用#

問題是當DLL丟失我的應用程序直接崩潰。我也嘗試過使用try-catch,但仍然是,應用程序崩潰了?

當我在主UI線程上調用DLL函數時,我的應用程序處理異常。

如何處理後臺線程中的異常?

mythread = new Thread(CM); 
mythread.IsBackground = true; 
mythread.Start(); 

private void CM() 
    { 
     // Perform a protection check with default options 
     try 
     { 
      ret_code = myclass.CheckProtection(myclass.CheckProtectionOptions.Default); 
     } 
     catch(Exception cm) 
     { 
      throw cm; 
     } 

}

+0

你能分享一下你試過的嗎 –

+0

什麼是你正在加載的DLL –

+0

我正在複製我的DLL到exe文件夾位置 – kaviarasan

回答

1

這裏快速的答案。

某些DLL與啓動它的第一個線程有親和力。我過去所做的就是讓該線程在後臺保持活動狀態,並帶有一個循環。然後您偵聽該DLL加載的線程中的事件。您可能需要重構代碼以偵聽事件,而不是調用DLL調用。

希望有幫助嗎?

我已經添加了一些示例代碼,您可以嘗試一下,看看會發生什麼。它不完美,但它應該有助於說明如何保持線程活着。還有其他方法可以做到這一點,但我只想保持示例簡單

using System; 
    using System.Reflection; 
    using System.Threading; 

    namespace ConsoleApplication3 
    { 
     internal class Program 
     { 
      private static void Main(string[] args) 
      { 
       var newThread = new Thread(DllLoader.DoWork); 
       newThread.Start(); 

       //My other application Logic 
      } 

      public class DllLoader 
      { 
       public enum ThingsICanDo 
       { 
        Jump, 
        Duck, 
        Run, 
        Quit 
       } 

       private static bool appStillRunning; 
       private static object myInstanceDllType; 

       private static void CheckForStuffToDo() 
       { 
        //Much better to use events, and pass the message inthe event 
        // then do what the message wants, and but I am keeping this breif 
        // for this example. 
        var DoNext = (ThingsICanDo) Enum.Parse(typeof (ThingsICanDo), Console.ReadLine(), true); 
        switch (DoNext) 
        { 
         case ThingsICanDo.Jump: 
          //Do jump stuff 
          Console.WriteLine("Jump"); 
          //myInstanceDllType.JumpStuff(); 
          break; 
         case ThingsICanDo.Duck: 
          Console.WriteLine("Duck"); 
          //myInstanceDllType.DuckStuff(); 
          //Do duck stuff 
          break; 
         case ThingsICanDo.Run: 
          Console.WriteLine("Run"); 
          //myInstanceDllType.RunStuff(); 
          //Do run stuff 
          break; 
         case ThingsICanDo.Quit: 
          //Do exit stuff 
          Console.WriteLine("Bye"); 
          Thread.CurrentThread.Abort(); 
          break; 
        } 
       } 

       public static void DoWork() 
       { 
        var externalAssembly = Assembly.LoadFrom("/path/my.Dll"); 
        myInstanceDllType = Activator.CreateInstance("DLLTypeINeed"); 
        while (appStillRunning) 
        { 
         try 
         { 
          CheckForStuffToDo(); 
         } 
         catch (Exception e) 
         { 
          //Log e 
          Console.WriteLine(e); 
         } 
         Thread.Sleep(1000); 
          //Much better to use semaphore.wait or something similar, but this is a simple example 
        } 
       } 
      } 
     } 
    } 
+0

有道理。但PLZ你可以發佈一些示例代碼? – kaviarasan

+0

這是相當複雜的,當我有機會的時候,我會嘗試爲你準備一個例子 –

+0

謝謝戴博克 – kaviarasan

1

屬於「你永遠不應該做的事情」類別。這是一個部署錯誤,你總是需要一個大聲的消息來告訴別人修復這個錯誤。但是,anyhoo,問題是try/catch被錯誤地放置。即時編譯器引發異常,它會在開始運行之前試圖生成機器代碼。用線程做這件事情會使事情變得更加複雜,它只能是可以捕獲它的CLR。

你必須要幫忙,你必須有意地寫一個你可以依賴的小存根方法來始終工作。然後它又必須調用有風險的代碼。現在你有辦法注入必要的try/catch。您還必須確保它在發佈版本中工作,這要求您減緩抖動並防止其將內存風險化。這需要一個屬性。像這樣:

using System.Runtime.CompilerServices; 
... 
mythread = new Thread(CMStub); 
mythread.IsBackground = true; 
mythread.Start(); 
... 

void CMStub() { 
    try { 
     CM(); 
    } 
    catch (Exception ex) { 
     LogFatalError(ex); // Don't throw! 
    } 
} 

[MethodImpl(MethodImplOptions.Noinlining)] 
void CM() { 
    // risky code here 
} 

原來的代碼用到了throw,那是行不通的。切勿忽略需要留下面包屑的情況,以便您可以知道線程沒有執行應有的操作。某種記錄器或EventLog類是絕對最低要求。

+0

即使我不扔。我的應用程序仍然崩潰? – kaviarasan

+0

意圖是讓你的LogFatalError()方法*不*崩潰你的應用程序,但只是報告它,讓有人可以找出你的應用程序爲什麼行爲不端。評論的模糊性提供了更多的理由,爲什麼你不應該這樣做。 –

+0

那麼沒有其他方法可以防止崩潰? – kaviarasan

相關問題