2012-02-09 14 views
3

私は名前付きシステムミューテックスを使って2つのプロセスを同期させています。これは私が現在、自分のアプリケーション内のミューテックスを取得しています方法です:MutexName名前付きシステムミューテックスが存在しない場合ミューテックスを取得する際の競合状態を回避する方法は?

using System.Threading; 

public static bool AcquireMutex() 
{ 
    // Protect against double acquisitions 
    if (MyMutex != null) 
    { 
     throw new ApplicationException("Failed to acquire mutex"); 
    } 

    try 
    { 
     // See if a named system mutex has already been created - if it has, 
     // wait a short amount of time for its release. 
     MyMutex = Mutex.OpenExisting(MutexName); 
     if (!MyMutex.WaitOne(TimeSpan.FromSeconds(2), false)) 
     { 
      // MyMutex still being held 
      MyMutex = null; 
      return false; 
     } 
    } 
    catch 
    { 
     // MyMutex doesn't exist so create it 
     MyMutex = new Mutex(true, MutexName); 
    } 

    return true; 
} 

OpenExistingは、私のアプリケーションは、それを作成することができ、例外がスローされます。

しかし、OpenExistingがスローすると、new Mutexの呼び出しの前に小さいウィンドウがあり、他のアプリケーションがそのミューテックスを取得している可能性があります。

この競合状態を回避し、このコードをより信頼できるものにする最良の方法は何ですか?

同僚は彼がコード内でWin32 Platform SDKのCreateMutex(同期が必要な他のプロセス)を使用していると述べました。ただし、これは.NET Frameworkによってネイティブにサポートされているようには見えません。だから私はそれが私のコードのための最善の解決策であるとは思わない。 @デビッドシュワルツからの回答をもとに


更新

、ここに私の新しいコードは次のとおりです。

public static bool AcquireMutex() 
{ 
    // Protect against double acquisitions 
    if (MyMutex != null) 
    { 
     throw new ApplicationException("Failed to acquire mutex"); 
    } 

    bool createdNew; 
    MyMutex = new Mutex(true, MutexName, out createdNew); 
    if (createdNew) 
    { 
     // Mutex was created so ownership is guaranteed; no need to wait on it. 
     return true; 
    } 

    try 
    { 
     if (!MyMutex.WaitOne(TimeSpan.FromSeconds(2), false)) 
     { 
      MyMutex = null; 
      return false; 
     } 
    } 
    catch (AbandonedMutexException) 
    { 
     // Other application was aborted, which led to an abandoned mutex. 
     // This is fine, as we have still successfully acquired the mutex. 
    } 

    return true; 
} 
+0

はい、これは機能しません。プロセスの1つをボス、それを作成するボスにする必要があります。 1つ、通常は最初のものを選んでください。他のプロセスがそれを開くことができない場合、本当に間違ったことがあります。それは待つ必要がある。 –

+0

@ハンス - 私はDavid Schwartzの答えに基づいて変更を加えました。私の最新のコードを見て、それが正しいかどうか教えてください。 – LeopardSkinPillBoxHat

+0

AbandonedMutexExceptionは、何かが重大に間違っている場合にのみスローされます。私は上記のコードのようにそれを沈黙させませんが、私のグローバル例外ハンドラはそれをさらに解析するためにログに記録させます。参照してください:https://msdn.microsoft.com/en-us/library/system.threading.abandonedmutexexception(v=vs.110).aspx –

答えて

4

この目的のために特別に設計されたコンストラクタがあります。
createdNew

タイプ:docsからローカルミューテックスが作成された場合可能System.Boolean
このメソッドが返す、名前がnullの場合、またはそれは、ある(真なるブールが含まれています空の文字列)、または指定された名前のシステムミューテックスが作成された場合。指定された名前のシステムミューテックスがすでに存在する場合はfalse。このパラメータは初期化されずに渡されます。

+0

答えをありがとう - 元の質問の私の更新されたコードを参照してください、それが正しいかどうか私に知らせてください。 – LeopardSkinPillBoxHat

関連する問題