我发现了一个场景,我的.Net应用程序会意外崩溃而不会引发任何异常。我希望至少AppDomain.UnhandledException
在这种情况下工作,以便至少能够记录错误并向用户提供一些信息。
在这种情况下,我有一个.Net程序集(让我们称之为 A ),并对本机DLL(我们称之为 B )进行互操作调用。 B创建一个线程并抛出;没有人能够捕获异常,我希望它能够一直向上堆栈,回到我的托管应用程序,最后成为一个未处理的异常。
此时我希望操作系统将控制权交还给.Net,后者会调用AppDomain.UnhandledException
,然后我的应用程序就会结束。但是,呼叫永远不会发生。
下面我提供了足够的信息来重现问题。它可以被忽略。
Program.cs的
internal class Program
{
public static void Main()
{
AppDomain.CurrentDomain.UnhandledException += _currentDomainUnhandledException;
try
{
BugDllInterop.ErrorMethod(0);
}
catch (Exception e)
{
Console.WriteLine("Exception: " + e.GetType().Name);
}
Console.WriteLine("Clean exit.");
}
private static void _currentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Console.WriteLine("Exception trapped.");
}
}
BugDllInterop.cs
public static class BugDllInterop
{
private const string BUG_DLL = "InteropExceptions.BugDll.dll";
[DllImport(BUG_DLL, CallingConvention = CallingConvention.Cdecl)]
public extern static void ErrorMethod(int i);
}
BugDll.h
// INCLUSION GUARD
#pragma once
#define DllExport __declspec(dllexport)
extern "C"
{
DllExport void ErrorMethod(int i);
}
BugDll.cpp
// HEADER /////////////////////////////////////////////////////////////////////
#include "BugDll.h"
// LIBRARIES //////////////////////////////////////////////////////////////////
#include <windows.h>
#include <fstream>
#include <iostream>
#include <time.h>
using namespace std;
// FUNCTIONS //////////////////////////////////////////////////////////////////
DWORD WINAPI threadMethod(LPVOID lpParameter)
{
throw 0;
return 0;
}
void ErrorMethod(int i)
{
DWORD myThreadID;
HANDLE myHandle = CreateThread(0, 0, threadMethod, 0, 0, &myThreadID);
WaitForSingleObject(myHandle, 3000);
CloseHandle(myHandle);
}
同样,我希望只是提出AppDomain.UnhandledException
事件。当然,如果有人知道如何正确处理异常以保持应用程序存活,那就更好了。
答案 0 :(得分:2)
您无法捕获和管理从另一个非托管线程抛出的异常。
当方法抛出异常时,CLR将仅在抛出异常的线程中搜索处理程序 。它甚至可以理解,因为线程的调用堆栈以线程本身开始。
你有一个 root 异常处理程序,因为CLR将处理程序放在顶层(一个会调用你的过滤器)但是对于非托管线程不是这样所以无法转发他们的例外。
这种情况的唯一解决方案是在发起它们的线程中捕获异常。如果您的线程函数可以抛出异常,那么在那里添加一个catch。无论如何不在管理方面。托管/非托管边界非常厚实。
您可能希望阅读有关异常处理的好文章:http://www.microsoft.com/msj/0197/exception/exception.aspx