2

Mutexを使用して、1台のマシンで起動するアプリのインスタンスを1つだけ許可できることを理解しています。これは、任意の数のユーザーが使用するデスクトップの数に関係なく、実行中のプログラムのインスタンスは最大で1つであることを意味します。

さて、1つのインスタンスだけを許可するのではなく、最大で2つだけ許可したいのですが、それ以上は許可しません。どうやってするの?私はこのようなコードを試しました:

    public static bool MutexChecking()
    {

            bool createNew1;
            // one set of GUID
            new Mutex(false, "54A8F2C1-6C11-4ED4-8A62-AD7C1D9F7970", out createNew1);



            if (createNew1)
                return true;
            bool createNew2;
             //another set
              new Mutex(false, "5E1C76D0-9897-412B-BD56-64A872F8FDE3", out createNew2);

            return createNew2;

    }

上記のコードは機能します...ある種。これは、これを除いて、私がテストしたすべてのケースで機能します。

  1. プログラムを開きます(それを呼びましょうp1
  2. プログラムをもう一度開きます(名前を付けましょうp2
  3. 閉じますp1
  4. プログラムを3回開きます(p3
  5. 期待:の間p3に、上記のメソッドはtrueを返す必要があります(であるcreateNew1必要があるためtrue)が、falseを返します(を createNew1返すためfalse)。

なんでそうなの?これを修正する方法はありますか?

4

4 に答える 4

1

必要なのは、ミューテックスではなく、セマフォです。ミューテックスは相互排除を処理し、セマフォは共有リソースの使用を最大数に制限します。

于 2012-06-29T03:43:43.570 に答える
0

これは、p2で最初のミューテックスを再度開くためです。このミューテックスは、p2が開いたままにするため、開いたままになります。最初のミューテックスを開いてすでに開いていることがわかったら、p2が2番目のミューテックスのみを開いたままにし、p1が最初のミューテックスのみを開いたままにするように閉じる必要があります。

于 2012-06-29T03:44:48.050 に答える
0

単純。outパラメーター(createdNew)のポイントを間違えています。ドキュメントから:

このメソッドが戻ると、ローカルミューテックスが作成された場合(つまり、名前がnullまたは空の文字列の場合)、または指定された名前付きシステムミューテックスが作成された場合にtrueとなるブール値が含まれます。指定された名前付きシステムミューテックスがすでに存在する場合はfalse。このパラメーターは初期化されずに渡されます。

あなたの場合、p2はすでに最初のミューテックスを作成しているので、「新しく作成」されていません。

あなたがしたいことは、アプリケーションによるミューテックスの作成に依存するのではなく、代わりにミューテックスの所有に依存することです。true最初の引数として渡し、アプリケーションの終了時にReleaseMutexを呼び出してみてください。

または、@ ChrisLattaが提案するように、名前付きセマフォに切り替えます。

于 2012-06-29T03:45:29.953 に答える
0

クリス・シェインの言ったことは正しい。あなたがする必要があるのは、ミューテックスを作成するだけでなく、所有することです。また、アプリケーションを終了するときにミューテックスを手動で解放する必要があります。そうしないと、他のアプリケーション インスタンスでAbandonedMutexExceptionが発生する可能性があります。

以下は、実装方法の簡単なコード例です。この特定のコードでは、StartInstance() と StopInstance() を同じスレッドで呼び出す必要があることに注意してください。

private static Mutex Mutex1 = new Mutex(false, "54A8F2C1-6C11-4ED4-8A62-AD7C1D9F7970");
private static Mutex Mutex2 = new Mutex(false, "5E1C76D0-9897-412B-BD56-64A872F8FDE3");
private static Mutex AcquiredMutex;

public static bool StartInstance()
{
    if (AcquiredMutex != null)
        return true;

    if (Mutex1.WaitOne(1))
    {
        AcquiredMutex = Mutex1;
    }
    else if (Mutex2.WaitOne(1))
    {
        AcquiredMutex = Mutex2;
    }

    return (AcquiredMutex != null);
}

public static void StopInstance()
{
    if (AcquiredMutex != null)
        AcquiredMutex.ReleaseMutex();
}

編集:実際には、複数のインスタンスを検出する方法としてcreateNewを使用したい場合は、おそらくそれを行うことができますが、Mutex はそのように設計されていないため、個人的にはお勧めしません。

ただし、createNewメソッドを使用することにした場合でも、アプリケーションが終了したら、自分でミューテックスを明示的に閉じる必要があります。

この方法論が前のものよりも優れている可能性がある 1 つの利点は、Close() メソッドを、それを作成した同じスレッドから呼び出す必要がないことです。

以下は、 createNewメソッドを使用した簡単なコード例です。スレッドセーフではないことに注意してください。スレッドセーフにするには、StartInstance() と StopInstance() で lock() を使用する必要があります。

private static readonly string[] MutexNames = new string[]
{
    "54A8F2C1-6C11-4ED4-8A62-AD7C1D9F7970",
    "5E1C76D0-9897-412B-BD56-64A872F8FDE3"
};

private static Mutex CreatedMutex;

public static bool StartInstance()
{
    if (CreatedMutex != null)
        return true;

    foreach (string name in MutexNames)
    {
        bool created;
        Mutex mutex = new Mutex(false, name, out created);

        if (created)
        {
            CreatedMutex = mutex;
            return true;
        }
        else
        {
            mutex.Close();
        }
    }

    return false;
}

public static void StopInstance()
{
    if (CreatedMutex != null)
        CreatedMutex.Close();
}
于 2012-06-29T08:12:47.753 に答える