我在后台线程中调用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 :(得分: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类是绝对最低要求。