:.する転載NETミューテックスをプロセスの境界を越えて同期して使用すること
ミューテックスは排他制御のための略語は、訪問のためのコンピュータ上で同じリソース上で、同時に2つのスレッドを防ぐために、ミューテックスです。しかし、他の排他的、スレッド境界を越えることができミューテックスと比較。
この記事で
何ミューテックスこと?
同期して他のスレッドと同じように、ミューテックスは、リソースへの排他的アクセスを提供します。ただし、システムリソースがミューテックスモニタ以上使用され、モニターが実現し、使用するC#のlockキーワードにロックすることです。
より強力なもたらし、より多くのシステムリソースを使用する - ミューテックスは、アプリケーションドメインの境界を越えてマーシャリングすることができ、スレッドは、プロセスの境界を越えて同期させることができます。
単純なミューテックス(クロスプロセスは、相互に排他的であることはできません)
最も簡単な方法は、直接、ミューテックスを使用することで new
、その後、出て Wait
待って、使用 ReleaseMutex
リリースされます。
1 プライベート 読み取り専用ミューテックス_mutex = 新しい新しいミューテックス(); 2 。3 プライベート ボイドUseResource() 4。 { 5。 _mutex.WaitOne(); 6 。7 // 短い待ち時間、私は公共資源の使用をふり。ここでは再入国の単一プロセス内のコードの一部はしませんです。 。8 のThread.sleep(500 ); 9 10 _mutex.ReleaseMutex(); 11 }
パラメータがある initiallyOwned
として指定された場合、パラメータ true
スレッドが呼び出したときに、これはミューテックススレッド(待つ必要はありません)を表し作成するためのリソースを持っている ReleaseMutex
他のスレッドが後に WaitOne
有効になります。
実際に私たちは、この排他モードを記述するためにあまり行かないようにしかし、このアプローチは、プロセス間の同期を達成することはできません。
クロスプロセスミューテックスのミューテックスを作成します。
クロスプロセスミューテックスのミューテックスを作成するには、ミューテックスは、名前を付けなければなりません。
使用する new Mutex(false, "Walterlv.Mutex")
プロセス間の排他的アクセスリソースの名前付きミューテックスのロックを作成します。
オーバーロードされたコンストラクタを使用する場合は、最初のパラメータ initiallyOwned
推奨値です false
。あなたは次のように指定されている場合ので、 true
あなたは、このスレッドが最初に作成されたこの願うことを示すために、時間 Mutex
のスレッドを、しかし、あなたはまっすぐなので new
出て、あなたは基本的に、あなたが最初のものではありません最後に知ることができないので、 new
アウト。
1 クラスプログラム 2 { 3。 静的 非同期タスクメイン(文字列[]引数) 4。 { 5。 VARのプログラム= 新しい新しいプログラム(); 6 ながら、(真の) 7。 { 8。 // 連続的にいくつかのリソースにアクセスしよう。このように、複数のプロセスが実行しているとき、あなたは、リソースへのアクセスの競合の高い確率をシミュレートすることができます。 9 program.UseResource(); 10 ザが待つ Task.Delay(50 ); 11 } 12である } 13である 14 15 プライベート ボイドUseResource() 16 { 17。 VARミューテックス= 新しい新しいミューテックス(falseに、" Walterlv.Mutex " ); 18である mutex.WaitOne(); 19 20である 。// 公共資源です。 21 // ここでも、2つの異なるプロセス、コードの一部が再入はありませんです。 22は、 VARのパス= @ " C:Users \ユーザー\ lvyi \デスクトップ\ walterlv.log " ; 23は Console.WriteLineを($ " [{DateTime.Now:Oは}]ファイル......書き始める" ); 24 File.AppendAllTextを(パス、$ " [{DateTime.Now:Oは}] ......ファイルの書き込みを開始します"、Encoding.UTF8); 25 のThread.sleep(1000年); 26である File.AppendAllText(パス、$ " [} {DateTime.Now:O]が完了ファイルに書き込まれる。" 、Encoding.UTF8); 27 Console.WriteLineを($ " [} {DateTime.Now:O]は、完全なファイルを書き込む。" ); 28 29 mutex.ReleaseMutex(); 30 } 31れます }
明らかに、我々は待機時間間隔のみ50ミリ秒のリソースを使用しますが、実際には待機時間が約1000ミリ秒で、このプログラムは二つのプロセスの影響の下で実行されていることに注意してください。プロセスオフ1つのターンの後、間隔は約50ミリ秒に復元します。
これは、ミューテックスがここで待っクロスプロセス相互排他における役割を果たして示しています。
あなたはそれが最初にいくつかの特別な処理の外に作成されるかどうかを必要とする場合には、使用して createdNew
コンストラクタ引数。
1 プライベート ボイドUseResource() 2 { 3 - VARミューテックス= 新しい新しいミューテックス(falseに、" Walterlv.Mutex " ); 4。 ++ VARミューテックス= 新しい新しいミューテックス(trueに、" Walterlv.Mutex "、OUT のvar createdNew); 5。 6。 - mutex.WaitOne(); 7 ++ // ミューテックスはcreatedNewが真であることを、ここから出て作成された場合、最初の引数は実際に起こったので、我々は待つ必要がinitiallyOwnedについて説明します。 8++ // すでにミューテックスが既に存在する準備ができての説明がある場合createdNewがfalseの場合、逆に、我々はここで待つ必要があります。 9 ++ IF(!CreatedNew) 10 ++ { 11。 ++ mutex.WaitOne(); 12である ++ } 13である ...... 14 mutex.ReleaseMutex(); 15 }
例外を処理
ApplicationExceptionを
mutex.ReleaseMutex();
現在のメソッドは、スレッドがこの関数を呼び出ししようとした場合にのみ、独自のスレッドの呼び出しすることができますが、ミューテックスを持っていなかった、スローされます ApplicationException
。
どのようにそれを持っていますか?以前のコンストラクタで覚えている initiallyOwned
パラメータのですか?それはあなたが(実際には、我々はまた、必要とするこのmutexの所有者であるかどうかを指定し、ある createdNew
これを確認支援します)。
スレッドがミューテックスを持っていない場合は、我々は、使用する必要が WaitOne
ロックを待機するために取得します。
AbandonedMutexException
1 クラスプログラム 2 { 3 静的 非同期タスクメイン(文字列[]引数) 。4 { 5 // スレッドを開き、ミューテックスは、そのスレッドで得失われました。 6 VARスレッド= 新しい新しいスレッド(AbandonMutex); 7 Thread.start(); 8 9 //はそれ以外の場合は、ミューテックス回収システムとなり、プロセスは終了させてはいけません。 10 Console.Read(); 11 } 12は、 13である プライベート 静的 ボイドAbandonMutex() 14 { 15 //は、ミューテックスを取得し、放出されなくなりました。 16 // ミューテックスが失われたように、このスレッドは、WAITONEの実行の終了時に終了しますので、。 17 VARミューテックス= 新しい新しいミューテックス(falseに、" Walterlv.Mutex " ); 18である mutex.WaitOne(); 19 } 20 }
あなたはこのプロセスを実行すると、このプロセスを維持するために最初の時間が終了していないと変なものは何もありません上記のコード、。しかし、その後、あなたがプロセスの2番目のインスタンスを起動し、それが中になります WaitOne
が、例外を受け取ります- AbandonedMutexException
。
あなたがコードを使用することができないのであれば try-finally
それがロックを取得した後にリリースされることを確認するために、そして強く推奨 WaitOne
例外をキャッチするとき。ところで、思い出させるtry-finally
非同期コードを持つことができない、あなたが見ることができます:内部使用は、(AutoResetEventなど)UIスレッド同期ロックの参加はデッドロックにつながる可能性が待っています。
言い換えれば、あなたは待つ必要があるとき、catch
異常に見えます。で catch
終了した後、あなたは再びそれを使用する必要はありません WaitOne
異常が発生した場合でも、あなたはまだロックを取得するので、待つことを。あなたが呼び出すことができることを ReleaseMutex
確認するために、我々は先に述べたように、ロックを解除することができ、ロックを保持しているスレッドのみという。
1つの プライベート 静的 ボイドWAITONE() 2 { 3。 VARミューテックス= 新しい新しいミューテックス(falseに、" Walterlv.Mutexは" ); 4 トライ 5 { 6 mutex.WaitOne(); 7 } 8。 キャッチ(AbandonedMutexException EX) 9。 { 10 Console.WriteLineを(" ロックされた放棄が見つかりました。" ); 11 } 12は、 Console.WriteLineを(" ロック取得" ); 13 }
参考資料
- ミューテックス - マイクロソフトドキュメント
- ミューテックスコンストラクタ(System.Threading) - マイクロソフトドキュメント
- ミューテックスクラス(System.Threading) - マイクロソフトドキュメント
この記事では、頻繁に更新される、オリジナルをお読みください: https://blog.walterlv.com/post/mutex-in-dotnet.html 、知識の古いエラー、より良い読書体験を誤解を避けるために。