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

时间:2017-03-04 07:26:49

标签: c# multithreading dll

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

}

2 个答案:

答案 0 :(得分: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
                    }
                }
            }
        }
    }

答案 1 :(得分:1)

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