4

.Netアプリケーションが例外を発生させずに予期せずクラッシュするシナリオを発見しました。少なくとも、AppDomain.UnhandledExceptionこの場合は、少なくともエラーをログに記録し、ユーザーに情報を提示できるようにするために、これが機能することを望んでいます。

このシナリオでは、ネイティブDLL(これをBと呼びます)への相互運用機能を備えた.Netアセンブリ(これをAと呼びます)があります。Bはスレッドを作成してスローします。例外をキャッチする人がいなければ、スタックの最後まで行き、管理対象アプリケーションに戻って、最終的に未処理の例外になると思います。

この時点で、OSが制御を.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イベントが発生することだけです。もちろん、アプリケーションを存続させるために例外を適切に処理する方法を誰かが知っているなら、それはさらに良いでしょう。

4

1 に答える 1

3

別のアンマネージスレッドからスローされた例外をキャッチして管理することはできません。

メソッドが例外をスローすると、CLRは、例外がスローされたスレッドでのみハンドラーを検索します。スレッドの呼び出しスタックはスレッド自体から始まるので、それも理解できます。

CLRがハンドラーをトップレベルに配置するため(フィルターを呼び出す)、ルート例外ハンドラーがありますが、これはアンマネージスレッドには当てはまらないため、例外を転送できません

この状況の唯一の解決策は、それらが発生したスレッドで例外をキャッチすることです。スレッド関数が例外をスローできる場合は、そこにキャッチを追加します。とにかく管理側ではありません。ここでは、管理された/管理されていない境界がかなり太くなっています。

例外処理に関するこの素晴らしい記事を読むことをお勧めします:http://www.microsoft.com/msj/0197/exception/exception.aspx

于 2012-04-23T14:28:17.613 に答える