10

ファイナライザーは常に .net フレームワークによって呼び出されるため、シーケンスが制御不能になる可能性があります。コンストラクタが失敗した場合でも、デストラクタをトリガーできます。

このようなファイナライザーの例外がサードパーティのライブラリから発生した場合、これは問題を引き起こす可能性があります: それらを処理する方法が見つかりません!

たとえば、次のコードでは、クラス A のコンストラクターは常に例外をスローして失敗しますが、A のファイナライザーは .net フレームワークによってトリガーされ、A には B 型のプロパティがあるため ~B() も呼び出されます。

class Program // my code
{
    static void Main(string[] args)
    {
        A objA;
        try
        {
            objA = new A();
        }
        catch (Exception)
        {
        }

        ; // when A() throws an exception, objA is null

        GC.Collect(); // however, this can force ~A() and ~B() to be called.

        Console.ReadLine();
    }
}

public class A  // 3rd-party code
{
    public B objB;

    public A()
    {
        objB = new B(); // this will lead ~B() to be called.
        throw new Exception("Exception in A()");
    }

    ~A() // called by .net framework
    {
        throw new Exception("Exception in ~A()"); // bad coding but I can't modify
    } 
}

public class B // 3rd-party code
{
    public B() { }

    ~B() // called by .net framework
    {
        throw new Exception("Exception in ~B()"); // bad coding but I can't modify
    } 
}

これらが私のコードである場合、少し簡単です-ファイナライザーでtry-catchを使用できます。少なくともログを記録できます-例外がプログラムをクラッシュさせ、エラーをできるだけ早く発見できるようにすることができます-または必要に応じて例外を「許容」し、try-catch を使用して例外を抑制し、正常に終了することができます。

しかし、A と B がサードパーティ ライブラリのクラスである場合、何もできません。発生する例外を制御することはできません。例外をキャッチすることもできないため、ログに記録したり抑制したりすることもできません。

私に何ができる?

4

3 に答える 3

2

サードパーティのユーティリティの記述が不十分なようです。:)

AppDomain.UnhandledExceptionを使用してキャッチしようとしましたか?

于 2011-07-18T02:06:49.080 に答える
0

GC.SuppressFinalizer(objA)GC.KeepAlive(objA)を使用KeepAliveすると、ガベージ コレクターがそのオブジェクトのファイナライズを呼び出すのを防ぐことができobjBますobjA。 . ただし、適切な方法でファイナライズまたは破棄するのを忘れた場合は、メモリ リークに注意する必要があります。objA

しかし、objAたとえばメソッドのある時点で別のメソッドが初期化objectBされ、それが適切に破棄されなかったとします。残念ながら、それについて何もできないと思います。

Releaseあなたが試すことができるもう1つのことは、モードではなくモードにいるときに、そのライブラリの動作が異なるかどうかを確認することDebugです。たとえば、ファイナライザーがデバッグモードで呼び出された場合にのみ、ファイナライザーで例外をスローする可能性があります。

~A()
{
#if DEBUG
    throw new Exception("Exception in ~A()");
#endif//DEBUG
} 

そうでない場合は、そのライブラリを扱うのに苦労することになると思います。

于 2011-07-18T03:03:58.953 に答える
0

アプリケーションのグローバル例外ハンドラーを検討することをお勧めします。ASP.NET、WinForm、MVC などを実行しているかどうかは示されていませんが、コンソール アプリケーションの場合は次のとおりです。

コンソール アプリケーションの .NET グローバル例外ハンドラ

ASP.NET では、Global.asax ファイルを使用して未処理の例外をキャッチできます。

アプリケーションで常に GC.Collect() を呼び出している場合は、それを try-catch ブロックでラップすることもできます。

考慮すべきいくつかのアイデア。

于 2011-07-18T02:07:42.463 に答える