4

我发现了一种情况,即我的 .Net 应用程序会意外崩溃而不会引发任何异常。我希望至少AppDomain.UnhandledException在这种情况下可以工作,以便我至少能够记录错误并向用户提供一些信息。

在这种情况下,我有一个 .Net 程序集(我们称之为A),其中包含对本机 DLL(我们称之为B)的互操作调用。B 创建一个线程并抛出;如果没有人捕捉到异常,我希望它会一直向上到堆栈,回到我的托管应用程序,然后最终成为未处理的异常。

在这一点上,我希望操作系统将控制权交还给.Net,它会调用AppDomain.UnhandledException,然后我的应用程序就会结束。但是,从来没有打过电话。

下面我提供了足够的信息来重现该问题。可以忽略。

程序.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);
}

错误DLL.h

// INCLUSION GUARD
#pragma once

#define DllExport __declspec(dllexport) 

extern "C" 
{
    DllExport void ErrorMethod(int i);
}

错误DLL.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引发事件。当然,如果有人知道如何正确处理异常以使应用程序保持活动状态,那就更好了。

4

1 回答 1

3

您无法捕获和管理从另一个非托管线程抛出的异常。

当方法引发异常时,CLR 将仅在引发异常的线程中搜索处理程序。甚至可以理解,因为线程的调用栈是从线程本身开始的。

您有一个异常处理程序,因为 CLR 将一个处理程序放在顶层(该处理程序将调用您的过滤器),但对于非托管线程而言并非如此,因此无法转发它们的异常

这种情况的唯一解决方案是在它们产生的线程中捕获异常。如果您的线程函数可以抛出异常,则在此处添加一个 catch。无论如何,不​​在托管方面。托管/非托管边界在这里非常厚。

您可能想阅读这篇关于异常处理的好文章:http: //www.microsoft.com/msj/0197/exception/exception.aspx

于 2012-04-23T14:28:17.613 回答