2009-03-11 21 views
13

を使用して対GC.KeepAlive、マイケル・コヴィントンこのコードを提示:アプリケーションの彼の<a href="http://www.ai.uga.edu/~mc/SingleInstance.html" rel="noreferrer">article about preventing multiple instances</a>で

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)は、早期ミューテックスを収集から、ガベージコレクタを防ぐために必要であることを説明して追加の参照がないためです。

私の質問:mutexをラッピングして同じことをしますか?つまり、以下のこともGCが私の下から敷物を引き出すのを妨げますか?

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

そして、私はm.Close()は十分にあるだろうと思うだろう:

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 
    } 
} 

私の腸の反応が使用しているため、動作します使用することと同じ(のはず)されていることですJITコンパイラに別の参照があることを通知し、早すぎるガベージコレクションを防止します。確かにゴミが収集されることを防ぐことができますusing文でmutexをラッピング

+0

私はCLRの専門家ではありません(なぜ私は回答を追加していません)が、あなたがしていることはうまくいくはずです。私はそれを試してみると言う。 –

+4

GCについて話すとき、「試してみてください」というのは悪い考えです。テストがうまくいくはずだったが、生産に失敗したケースがあった。リリースとデバッグモードでJITコンパイラがどのように動作するかの違いが多くあります。 –

答えて

17

しますが、最後にそれのにdispose(それはないCloseDispose()呼び出しに対しGC.KeepAliveしません、明らかに)。

この方法の最後が本当にプロセスの終わりになるのであれば、私はそれが実用的な違いを生み出すとは思わない - 私はusingの文章を、 IDisposableを実装しています。

プロセスが終了したときにmutexが破棄されていない場合は、他のファイナライザがタイムアウトを超えてファイナライゼーションスレッドを処理しない限り、ファイナライザが処理すると考えられます。

ファイナライザがそれを処理しない場合、Windowsプロセス自体がおそらくmutexを所有していないことに気づくかどうかわかりません。もっと。私はそれが間違いないと思っていますが、確かに知るには詳細なWin32のマニュアルを調べなければなりません。

+1

あなたはそうです、CloseではなくDisposeを呼び出しますが、このインスタンスでは同じであることが分かります(Close呼び出しDispose)。 SDKのドキュメントによれば、mutexはプログラムの終了時に解放されます。あなたのように、私は同じ理由で使うのが好きです。 –

+0

GC.KeepAlive(m)の呼び出しが実際に重要でないように、プロセスがシャットダウンするまでApplication.Run(新しいForm1())の呼び出しが返されないので、この質問を見ましたか? – Benny

+4

@Benny:そうです。その呼び出しがなければ、オブジェクトはガベージコレクションされる可能性があるからです。 'GC.KeepAlive'への呼び出しが存在するという事実は、GCが' m'を "ルート"参照とみなさなければならないことを意味します。 –

5

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

廃棄することなくMutexを吊り下げたままにしておくと、アプリケーションがシャットダウンしているときのクリーンアップ作業の程度に応じて、ファイナライズされるまでに時間がかかることがあります。

-2

KeepAliveがMutexと一緒に使用されている理由は、それが早くガベージコレクションされていないことを確認することだと思います。 C#using/Disposeパターンはそれに対して保護されていません。スコープ内でオブジェクト参照が使用されなくなった場合、ランタイムはスコープの終了前にオブジェクト参照を収集します。それは最適化です。

+1

<< C#using/Disposeパターンは保護されていません>> その主張を裏付ける証拠を提供できますか?テストケース、ドキュメントのいずれか? ありがとう! – EricLaw

関連する問題