15

アプリケーションの複数インスタンスの防止に関する記事で、Michael Covington は次のコードを提示しています。

static void Main()                  // args are OK here, of course
{
    bool ok;
    m = new System.Threading.Mutex(true, "YourNameHere", out ok);

    if (! ok)
    {
        MessageBox.Show("Another instance is already running.");
        return;
    }

    Application.Run(new Form1());   // or whatever was there

    GC.KeepAlive(m);                // important!
}

彼は、GC.KeepAlive(m) は、ミューテックスへの追加の参照がないため、ガベージ コレクターがミューテックスを早期に収集するのを防ぐために必要であると説明しています。

私の質問: ミューテックスを using でラップすると、同じことができますか? つまり、次のことも GC が私の下から敷物を引き出すのを防ぐのでしょうか?

static void Main()                  // args are OK here, of course
{
    bool ok;
    using (var m = new System.Threading.Mutex(true, "YourNameHere", out ok))
    {
        if (! ok)
        {
            MessageBox.Show("Another instance is already running.");
            return;
        }

        Application.Run(new Form1());   // or whatever was there
    }
}

私の直感的な反応は、 using は次と同等である(と思われる)ため、 using が機能するということです。

Mutex m = new System.Threading.Mutex(true, "YourNameHere", out ok);
try
{
    // do stuff here
}
finally
{
    m.Close();
}

そして、 m.Close() があれば、別の参照があることを JIT コンパイラに通知するのに十分であり、時期尚早のガベージ コレクションを防ぐことができると思います。

4

3 に答える 3

19

ミューテックスをusingステートメントでラップすると、実際にはガベージコレクションが防止されますが、最後に破棄されます(ではなく呼び出します)(明らかにそうではありません)。DisposeCloseGC.KeepAlive

メソッドの終わりが本当にプロセスの終わりになる場合、私はあなたが使用する実際的な違いを生む可能性は低いと思いusingますIDisposable.

プロセスの終了時にミューテックスが破棄されていない場合、他のファイナライザーがタイムアウトを超えてファイナライズ スレッドを占有しない限り、そのファイナライザーがそれを処理すると思われます。

ファイナライザーがそれを処理しない場合、プロセス (プロセス) が存在しないことを考えると、プロセスがミューテックスを所有できない可能性があることに Windows 自体が気付くかどうかはわかりません。そうなると思いますが、確実に知るには詳細な Win32 ドキュメントを確認する必要があります。

于 2009-03-11T18:00:32.750 に答える
5

この場合、 を使用するよりも を使用usingする方が適しているようGC.KeepAliveです。アプリケーションが実行されている限り、アプリケーションを存続させたいだけでなくMutex、メイン ループを終了するとすぐにアプリケーションを消滅させたいと考えています。

ハングアップを破棄せずにそのままにしておくMutexと、アプリケーションのシャットダウン時に実行するクリーンアップ作業の量によっては、ファイナライズされるまでに時間がかかる場合があります。

于 2009-03-11T18:17:35.390 に答える
-2

名前付きMutexでKeepAliveを使用する理由は、早期にガベージコレクションが行われないようにするためだと思います。/ Disposeパターンを使用するC#は、それから保護するためのものではありません。オブジェクト参照がスコープ内で使用されなくなると、ランタイムはスコープの終了前にオブジェクト参照を収集する場合があります。それは最適化です。

于 2009-04-24T19:21:22.593 に答える