本机线程崩溃的例外.Net应用程序无一例外

时间:2012-04-23 13:59:15

标签: .net exception interop

我发现了一个场景,我的.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事件。当然,如果有人知道如何正确处理异常以保持应用程序存活,那就更好了。

1 个答案:

答案 0 :(得分:2)

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

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

你有一个 root 异常处理程序,因为CLR将处理程序放在顶层(一个会调用你的过滤器)但是对于非托管线程不是这样所以无法转发他们的例外

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

您可能希望阅读有关异常处理的好文章:http://www.microsoft.com/msj/0197/exception/exception.aspx