2017-03-04 81 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

相关问题