私はまさにこの目的のために Mutex をうまく使用しており、いくつかの癖がありましたが、それが機能することを確認できました。
私は自宅で完全に機能するコード例を持っています。今晩コード例を追加してほしい場合は、この回答にコメントを投稿してください。
アップデート:
これは、本番アプリのコードを簡略化したものです。これはコンソール アプリですが、どのタイプのアプリケーションにも同じ原則が適用されます。コマンドライン引数を指定して実行
--mutex
ミューテックス ロジックをテストします。
私の場合、ミューテックスは実際にほとんどのプロセスを保護しますが、そのように使用する必要がある理由はありません。それがこの場合に必要だったものです。
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Threading;
namespace MyNameSpace
{
class Program
{
// APP_GUID can be any unique string. I just opted for a Guid. This isn't my real one :-)
const string APP_GUID = "1F5D24FA-7032-4A94-DA9B-F2B6240F45AC";
static int Main(string[] args)
{
bool testMutex = false;
if (args.Length > 0 && args[0].ToUpper() == "--MUTEX")
{
testMutex = true;
}
// Got variables, now only allow one to run at a time.
int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
int rc = 0;
Mutex mutex = null;
bool obtainedMutex = false;
int attempts = 0;
int MAX_ATTEMPTS = 4;
try
{
mutex = new Mutex(false, "Global\\" + APP_GUID);
Console.WriteLine("PID " + pid + " request mutex.");
while (!obtainedMutex && attempts < MAX_ATTEMPTS)
{
try
{
if (!mutex.WaitOne(2000, false))
{
Console.WriteLine("PID " + pid + " could not obtain mutex.");
// Wait up to 2 seconds to get the mutex
}
else
{
obtainedMutex = true;
}
}
catch (AbandonedMutexException)
{
Console.WriteLine("PID " + pid + " mutex abandoned!");
mutex = new Mutex(false, "Global\\" + APP_GUID); // Try to re-create as owner
}
attempts++;
}
if (!obtainedMutex)
{
Console.WriteLine("PID " + pid + " gave up on mutex.");
return 102;
}
Console.WriteLine("PID " + pid + " got mutex.");
// This is just to test the mutex... keep one instance open until a key is pressed while
// other instances attempt to acquire the mutex
if (testMutex)
{
Console.Write("ENTER to exit mutex test....");
Console.ReadKey();
return 103;
}
// Do useful work here
}
finally
{
if (mutex != null && obtainedMutex) mutex.ReleaseMutex();
mutex.Close();
mutex = null;
}
return rc;
}
}
}