6

私のクラスの 1 つは、アプリケーションの実行中に統計を収集し、アプリケーションの終了時にこの統計をディスクに保存したいと考えています。プログラム内でこのクラスを破棄することは決してないので、次のようにログをファイルに保存しようとしました:

    ~Strategy()
    {
        foreach(var item in statisticItems)
        {
            log.WriteLine(item.Text);    // log is AutoFlush
        }
    }

ただし、表示されるはずのログが表示されず、デストラクタが呼び出されたときにデバッガーの瞬間を「キャッチ」することもできません。

質問:

  • デストラクタが呼び出された瞬間をデバッガでキャッチできないのはなぜですか? プログラムが終了したら、すべてのオブジェクトに対してデストラクタを呼び出す必要がありますか?
  • 自分のものをログに記録するには何を使用すればよいですか?
4

3 に答える 3

1

デストラクタ (またはファイナライザ) は、そのようなコードを配置する場所ではありません。管理されていないリソースを解放するために設計されています。デストラクタは非決定論的に呼び出されるため、デストラクタ内でオブジェクトが有効であることに依存することはできません。また、非常に特殊な状況下で別のスレッドで呼び出されるため、デバッガーでキャッチすることはできません。つまり、デストラクタを使用する必要があることがわかっている場合を除き、使用しないでください。

アプリケーションのシャットダウンをログに記録する理想的な方法は、単純にメソッドの最後にログ コードを配置するMainことです。スローされた例外を必ずキャッチしてログに記録する必要があります。その場合は、 の最後にシャットダウンをログに記録できますMain

スタック オーバーフローなどのエラーが原因で、シャットダウンをログに記録できない特殊なケースがいくつかあります。そのような場合、エラーの前に何が起こったかのログに頼る必要があります。

于 2012-07-17T19:38:06.127 に答える
-1

デストラクタに依存しないでください。次のようなものを使用することをお勧めします。

[STAThread]
static void Main()
{
    using(new Strategy())
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
}

public class Strategy : IDisposable
{
    public void Dispose()
    {
        WriteLogs()
    }
    ...
}

このようにして、ログが確実に書き込まれます。

静的なvoidMainは、Windowsフォームアプリケーションの作成時に作成されるデフォルトのprogram.csからコピーされます。

于 2012-07-17T19:24:03.677 に答える
-1

これは(まだ)完全な答えではありませんが、これをチェックしてください:

デストラクタがいつ呼び出されるかは、ガベージ コレクタによって決定されるため、プログラマは制御できません。ガベージ コレクターは、アプリケーションで使用されなくなったオブジェクトをチェックします。オブジェクトを破棄できると判断した場合は、デストラクタ (存在する場合) を呼び出し、オブジェクトの格納に使用されたメモリを解放します。デストラクタは、プログラムの終了時にも呼び出されます。

出典: MSDN

コンソール アプリの場合は、電話Environment.Exit(0);してどうなるか確認していただけますか。

これは興味深い質問なので、この回答を最新の状態に保ちましょう。誰でも自由に編集してください。

よろしく

于 2012-07-17T19:32:48.170 に答える