C# 如何在c中处理线程内的dll函数调用#
我正在后台线程中调用一个DLL函数 问题是当DLL丢失时,我的应用程序直接崩溃。我也尝试了try-catch,但应用程序还是崩溃了 当我在主UI线程上调用DLL函数时,我的应用程序将处理异常 如何在后台线程中处理异常C# 如何在c中处理线程内的dll函数调用#,c#,multithreading,dll,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 wi
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
}
}
}
}
}
快速回答这里
某些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的方法。您还必须确保这在发布版本中起作用,这需要您减缓抖动并防止它内联危险的方法。这需要一个属性。像这样:
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
}
使用的原始代码抛出,无法工作。永远不要跳过留下面包屑的需要,这样你就可以知道线程没有完成它应该做的事情。某种类型的记录器或EventLog类是绝对最低要求。属于“永远不应该做的事情”类别。这是一个部署错误,您总是需要一个响亮的消息来告诉某人去修复它。但无论如何,问题是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
}
使用的原始代码抛出,无法工作。永远不要跳过留下面包屑的需要,这样你就可以知道线程没有完成它应该做的事情。某种类型的记录器或EventLog类是绝对最低要求。您可以共享您尝试过的内容吗您正在加载的DLL是什么?我正在将我的DLL复制到exe文件夹位置。您是否真的捕获到异常,或者它是否失效?用断点检查。哦,在抛出后,我想是的,我没能捕捉到。但是有可能从bck线程捕获异常吗?你能分享你尝试过的吗?你正在加载的DLL是什么?我正在将我的DLL复制到exe文件夹位置。你真的捕获了异常吗?还是它失败了?用断点检查。哦,在抛出后,我想是的,我没能捕捉到。但有可能从bck线程捕获异常吗?这很有意义。但请你发一些示例代码好吗?它很复杂,我会尝试在我有机会的时候为你准备一个示例。但请你发一些示例代码好吗?这很复杂,我会在有机会的时候给你准备一个例子,即使我不扔。我的应用程序还是会崩溃?目的是让LogFatalError()方法不会崩溃你的应用程序,而只是报告它,以便有人能找出你的应用程序出现错误的原因。评论的模糊性提供了更多的理由说明为什么你根本不应该这么做。所以没有其他方法可以防止崩溃?总之,我的应用程序中已经有了一个事件记录器。我至少可以在那里记录这次事故。顺便说一句,谢谢你的建议。即使我不扔。我的应用程序还是会崩溃?目的是让LogFatalError()方法不会崩溃你的应用程序,而只是报告它,以便有人能找出你的应用程序出现错误的原因。评论的模糊性提供了更多的理由说明为什么你根本不应该这么做。所以没有其他方法可以防止崩溃?总之,我的应用程序中已经有了一个事件记录器。我至少可以在那里记录这次事故。顺便说一句,谢谢你的建议。