最近、ジョブ スケジューリング用の ConsoleApp に取り組んでいます。この記事では、ジョブ スケジューリングの部分については説明しません (後で書きます)。この記事では、単一インスタンスの動作を保証する方法についてのみ説明します。
ConsoleApp の実行要件
1. システムの起動時にアプリケーションを起動します。
2. 各セッションで実行される単一のインスタンス。
リモート デスクトップ リンクを開くときは、ConsoleApp のインスタンスを 1 つだけ起動できます。
3. システム内で実行できるインスタンスは 1 つだけです。
複数のリモート デスクトップ リンクが開かれている場合、ConsoleApp のインスタンスは 1 つだけ起動できます。
ミューテックス
Mutex: プロセス間の同期にも使用できる同期プリミティブ。
表示される MSND: http://msdn.microsoft.com/zh-cn/library/system.threading.mutex.aspx
公式文書の紹介文にこんな一節があります
ターミナル サービスを実行しているサーバーでは、名前付きシステム ミューテックスは 2 つのレベルの可視性を持つことができます。名前がプレフィックス「Global」で始まる場合、ミューテックスはすべてのターミナル サーバー セッションで表示されます。名前が接頭辞「Local」で始まる場合、ミューテックスはそれが作成されたターミナル サーバー セッションでのみ表示されます。この場合、サーバー上の他のすべてのターミナル サーバー セッションに同じ名前の個別のミューテックスを設定できます。プレフィックスを指定せずに名前付きミューテックスを作成した場合、プレフィックス「Local」が付けられます。ターミナル サーバー セッションでは、名前のプレフィックスのみが異なる 2 つのミューテックスは独立したミューテックスであり、これら 2 つのミューテックスはターミナル サーバー セッション内のすべてのプロセスに表示されます。つまり、プレフィックス名 "Global" と "Local" は、ターミナル サーバー セッションを基準とした (プロセスを基準としたものではなく) ミューテックス名のスコープを示します。
残念ながら、この部分は次のように理解できる C# の例が見つかりませんでした。
mutexName= "ローカル\" +"アプリ名";
これは、それが作成されたセッションに対してのみ有効です。つまり、新しいリモート接続が開かれると、ConsoleApp インスタンスが再び開始されます。
mutexName= "グローバル\" +"アプリ名";
すべてのセッションに有効です。複数のリモート リンクが開かれている場合、最初のリモート リンクのみが ConsoleApp インスタンスを正常に開始します。
セッションごとに単一のインスタンスとして実行
プライベート静的 void LocalMutex()
{
// 初めてミューテックスを作成するかどうか
bool newMutexCreated = false;
string mutexName = "ローカル\" + "tenghoo";
ミューテックス ミューテックス = null;
試す
{
mutex = new Mutex(false, mutexName, out newMutexCreated);
}
catch (例外例)
{
Console.Write(例:メッセージ);
System.Threading.Thread.Sleep(3000);
環境.Exit(1);
}
// 初めてミューテックスを作成します
if (newMutexCreated)
{
Console.WriteLine("プログラムが開始されました");
//todo: 実行するタスクは次のとおりです
}
それ以外
{
Console.Write("別のウィンドウがすでに実行されており、3 秒後に自動的に閉じます...");
System.Threading.Thread.Sleep(1000);
Console.Write("1");
System.Threading.Thread.Sleep(1000);
Console.Write("2");
System.Threading.Thread.Sleep(1000);
Console.Write("3");
Environment.Exit(1);//プログラムを終了する
}
}
システム全体の単一インスタンスの操作
プライベート静的 void GlobalMutex()
{
// 初めてミューテックスを作成するかどうか
bool newMutexCreated = false;
string mutexName = "グローバル\" + "tenghoo";
ミューテックス ミューテックス = null;
試す
{
mutex = new Mutex(false, mutexName, out newMutexCreated);
}
catch (例外例)
{
Console.Write(例:メッセージ);
System.Threading.Thread.Sleep(3000);
環境.Exit(1);
}
// 初めてミューテックスを作成します
if (newMutexCreated)
{
Console.WriteLine("プログラムが開始されました");
//todo: 実行するタスクは次のとおりです
}
それ以外
{
Console.Write("別のウィンドウがすでに実行されており、3 秒後に自動的に閉じます...");
System.Threading.Thread.Sleep(1000);
Console.Write("1");
System.Threading.Thread.Sleep(1000);
Console.Write("2");
System.Threading.Thread.Sleep(1000);
Console.Write("3");
Environment.Exit(1);//プログラムを終了する
}