【问题标题】:How to handle dll function calls inside a thread in c#如何在c#中处理线程内的dll函数调用
【发布时间】:2017-03-04 07:26:49
【问题描述】:

我正在后台线程中调用其中一个 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;
        }

}

【问题讨论】:

  • 你能分享你的尝试吗
  • 你加载的DLL是什么
  • 我正在将我的 DLL 复制到 exe 文件夹位置
  • 你真的捕捉到异常还是失败了?检查断点。
  • 投掷后糟糕,我想我没能接住。但是是否可以从 bck 线程中捕获异常?

标签: c# multithreading dll


【解决方案1】:

属于“你不应该做的事情”类别。这是一个部署错误,你总是需要一个响亮的信息来告诉别人修复它。但是无论如何,问题是 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 类是绝对最低要求。

【讨论】:

  • 即使我不扔。我的应用程序仍然崩溃吗?
  • 目的是让您的 LogFatalError() 方法使您的应用程序崩溃,而只是报告它,以便有人可以找出您的应用程序行为不端的原因。评论的模糊性提供了更多你不应该这样做的理由。
  • 那么就没有其他办法防止崩溃了吗?
  • 无论如何,我的应用程序已经有一个事件记录器。我至少可以在那里记录崩溃。顺便说一句,谢谢您的建议。
【解决方案2】:

在这里快速回答。

某些 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
                    }
                }
            }
        }
    }

【讨论】:

  • 有道理。但是请您发布一些示例代码吗?
  • 比较复杂,有机会我会试着给你准备一个例子
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-12
  • 1970-01-01
  • 2015-03-08
  • 2014-01-01
  • 2014-04-11
  • 1970-01-01
  • 2021-03-15
相关资源
最近更新 更多