• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:VS2005 C#での質問です。)

VS2005 C#でのミューテックス取得時の重複起動防止がうまくいかない

このQ&Aのポイント
  • VS2005 C#での質問です。ミューテックスを使用してスレッドの重複起動を防ごうとしていますが、ミューテックスを取得する際に毎回取得できてしまい、重複起動を防ぐことができません。どなたか解決策を教えてください。
  • C#でミューテックスを使用してスレッドの重複起動を防ぎたいのですが、取得したミューテックスが毎回取得できてしまい、重複起動を防ぐことができません。解決策を教えてください。
  • VS2005のC#でミューテックスを使用していますが、スレッドの重複起動を防げません。ミューテックスを取得する際に問題があります。どのように解決すればよいでしょうか。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

>現状の問題としては(2)にあるように、(b)を実行したあと、(c)を実行していないのに再度(b)が通ることです。なぜ取得できてしまうでしょうか。  Mutexはスレッド間やプロセス間の排他制御に使われます。  すでに使用権を持っているスレッドがWaitOneを呼び出した時は、内部カウンタをインクリメントした上でtrueで返るようです。内部カウンタはReleaseMutex呼び出し毎にデクリメントされ、0になれば使用権が解放されるようです。  質問のコードだとすべて同一のスレッドで呼び出されることになるので、WaitOneの結果は常にtrueで返ってくることになります。  したがってMutexで排他制御をおこなう場合は、WaitOne呼び出し後にスレッドを起動するのではなく、起動したスレッドからWaitOneを呼び出すようにする必要があります。同様にReleaseMutexもスレッドの終了時に呼び出します。 (1)スレッド起動 (2)名前付きMutex生成 (同じ名前を持つMutex間で排他制御が行われます) (3)WaitOne呼び出し (4)スレッドの処理本体 (5)ReleaseMutex呼び出し (6)スレッド終了

abcron
質問者

お礼

使用権を必要とするスレッド内でWaitOne呼び出し/ReleaseMutex呼び出しを行うことで重複起動を防げました。 やはり元スレッドで取得/解放していたことに原因があったようです。 細かく説明して頂きありがとうございました。

その他の回答 (2)

回答No.2

>if (state[i]) >{ >//ミューテックス取得 >if (mt.get(i)) ★i=0のときは解放していないのに毎回trueになる。 >{ >L_process[i].BeginInvoke(i, null, null); >mt.keep(i); >} >} >else >{ >//ミューテックス開放 >if (mt.get(i)) ★i=0のときは通らない >{ >mt.release(i); >} >} >} (1)stateが領域獲得されただけで何も代入されていないので、falseで初期化されていると、この中の処理は実行されません。 (2)取得と解放のところで同じようにmt.get(i)が呼び出されていますが、取得時に獲得された使用権は解放処理がなされるまで解放されないので、解放のところの呼び出しでは必ずfalseで帰ってくるので、永遠に使用権が解放されないのではないですか? 「i=0のとき」とか書いてありますが、i=1でもi=2でも同じような気がしますが。 (3)GC.KeepAliveが何を意図しているのか不明です。  最低1回でもmt.get(i)が呼び出されてたらmutex_objがガベージコレクションの対象になる可能性はほとんどないと思われますが。

abcron
質問者

お礼

所々抜粋したものをサンプルとして上げてしまったのでロジックが狂っていました。 申し訳ありません。 処理の流れとしては以下になります。 (a) タイマコールバックによりstateを0か1に変化 (b) state=1のとき、ミューテックスを取得しメソッド実行 (c) state=0のとき、ミューテックスを取得しているようならメソッドを強制終了しミューテックス解放 ご指摘の(1)に関しては、Main()のwhileループ前でstate変化用のタイマを起動し、裏でstateを変化させています。 (2)はご指摘通りです。抜けてました。(メソッド強制終了処理も) (3)のGC.KeepAliveについてはこのサイトを参考にしています。意図はよく分かっていません。  http://jeanne.wankuma.com/tips/csharp/process/mutex.html 現状の問題としては(2)にあるように、(b)を実行したあと、(c)を実行していないのに再度(b)が通ることです。なぜ取得できてしまうでしょうか。

abcron
質問者

補足

記述漏れがありました。 実行されたスレッド(L_Run)は内部で無限ループとなっており帰ってきません。 #さらにGC.KeepAliveの意味がないですね。。。

回答No.1

毎回Mutexクラスのオブジェクトを生成してたら排他制御にはなりません。 こことか、使い方をちゃんと読んでますか? http://msdn.microsoft.com/ja-jp/library/system.threading.mutex.aspx 基本的にリソース1個に対し1つのstaticなMutexを生成し、それによって排他制御を行います。 生成されたMutexを用いた排他制御の方法は基本的に次の手順です ・WaitOneメソッドを呼び出す  (リソースが使用中なら解放されるまで待ち、解放されたらリソースの使用権が割り当てられる) ・リソースを用いた処理 ・ReleaseMutexを呼び出す  (リソースの使用権の解放) 基本的にMutexはリソース1個に対して1個の使用権で排他制御をおこなうだけなので、複数個のリソースがある場合はリソース個々に対して別個のMutexを生成して個別に排他制御するか、あるいはMutexじゃなくSemaphoreを使って排他制御をおこなうことになります。

abcron
質問者

お礼

回答ありがとうございます。 サンプルが分かりづらく申し訳ありません。 サンプルに関しては次の回答で説明させていただきます。 私としてはMクラス内で宣言しているMutex配列の宣言と、M.setのミューテックス生成に問題があるような気がしています。

関連するQ&A