繁体   English   中英

如何在C#中的线程内部处理dll函数调用

[英]How to handle dll function calls inside a thread in 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;
        }

}

在这里快速回答。

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

属于“您不应该做的事”类别。 这是一个部署错误,您总是需要大声的消息来告诉别人进行修复。 但是,问题在于,try / catch放置不正确。 即时编译器会抛出该异常,它会在尝试开始运行之前试图生成机器代码,因此会产生异常。 用线程执行此操作会使它更加复杂,只有CLR才能捕获它。

您将需要帮助,您必须有意识地编写一些可以持续工作的存根方法。 然后,它又必须调用危险代码。 现在,您可以注入必要的try / catch。 您还必须确保这在Release版本中有效,这要求您减慢抖动并防止它嵌入危险的方法。 这需要一个属性。 像这样:

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类是绝对最低要求。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM