ソリューションのスタートアップ プロジェクト間に遅延を追加する方法は?
WindowsService を起動してから 2 ~ 3 秒後に Client プロジェクトを起動したい。
なぜこれが必要なのですか?
WindowsService はソケット サーバーを実行し、Client はソケットを実行してサーバーに接続します。WindowsService の読み込みはクライアントよりも遅く、これにより、まだ実行されていないサーバーに接続するときにクライアント側で例外が発生します
ソリューションのスタートアップ プロジェクト間に遅延を追加する方法は?
WindowsService を起動してから 2 ~ 3 秒後に Client プロジェクトを起動したい。
なぜこれが必要なのですか?
WindowsService はソケット サーバーを実行し、Client はソケットを実行してサーバーに接続します。WindowsService の読み込みはクライアントよりも遅く、これにより、まだ実行されていないサーバーに接続するときにクライアント側で例外が発生します
おそらく、クライアント内に再試行メカニズムを追加します。そうすれば、「Visual Studio からの起動」の場合に役立つだけでなく、実際のクライアントが接続している間にサーバーがたまたま再起動する場合にも役立ちます。サーバーがより高速なマシン上にあるという事実は、サーバーを再起動する必要がないという意味ではありませんね?
実際、接続中にサーバーが再起動された場合でもクライアントが回復できるように、この再試行メカニズムを追加することをお勧めします。もちろん、それはプロジェクトが何をしているかに依存します。
Mutex ロックを使用して、2 つのスタートアップ プロジェクトを同期できます。
プログラム 1 (スタートアップ プロジェクト 1):
namespace ConsoleApplication1
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
class Program1
{
private static bool isNewMutexCreated = true;
private static Mutex mutex;
static void Main(string[] args)
{
mutex = new Mutex(true, "Global\\ConsoleApplication1", out isNewMutexCreated);
AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
Console.WriteLine("Application1 executed on " + DateTime.Now.ToString());
Console.ReadKey();
}
static void CurrentDomain_ProcessExit(Object sender, EventArgs e)
{
if (isNewMutexCreated)
{
Console.WriteLine("Mutex Released");
mutex.ReleaseMutex();
}
}
}
}
プログラム 2 (スタートアップ プロジェクト 2):
namespace ConsoleApplication2
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
class Program2
{
static void Main(string[] args)
{
Mutex mutex = null;
Thread.Sleep(5000);
while (mutex == null)
{
try
{
mutex = Mutex.OpenExisting("Global\\ConsoleApplication1");
}
catch (Exception)
{
Console.WriteLine("Mutex not found on " + DateTime.Now.ToString());
Thread.Sleep(3000);
}
}
Console.WriteLine("Application2 executed on " + DateTime.Now.ToString());
Console.ReadKey();
}
}
}
テストのもう 1 つの簡単なオプションは、デバッガーが次のようにアタッチされている場合にクライアントを遅らせることです。
if (System.Diagnostics.Debugger.IsAttached)
{
System.Threading.Thread.Sleep(2000);
}
#if DEBUG
必要に応じて、ブロックでラップすることもできます。とにかく、これは最小限の作業量であるべきだと思います:)
複数のスタートアップ プロジェクトの場合、それらは指定された順序でロードされ、同時にもランダムにもロードされません。 http://msdn.microsoft.com/en-us/library/09138bex(v=vs.90).aspx
したがって、「window service」の後に「client」を指定すると、うまくいくかもしれません。また、上記で提案したコード化された方法を取得したくない場合は、(テストの場合のみ) 必要な遅延の後に別のソリューションからソリューションに「クライアント」プロセスを手動でアタッチできます。 http://msdn.microsoft.com/en-us/library/c6wf8e4z(v=vs.100).aspx
クライアントを後で開始する必要がある場合は、リストを調整する必要があります。
また、「/wait」をコーディングします。これは、そのフラグが見つかった場合にアプリをロードするときに、それを待機するのにも役立つかもしれません。
サーバー プロジェクトを単一のスタートアップ プロジェクトとして設定し、このマクロを使用してサーバーとクライアントを遅延して起動できます。
Sub DebugServerAndClientWithDelay()
DTE.Debugger.Go(False)
System.Threading.Thread.Sleep(2000)
DTE.Windows.Item(Constants.vsWindowKindSolutionExplorer).Activate()
DTE.ActiveWindow.Object.GetItem("SolutionName\ClientProjectName").Select(vsUISelectionType.vsUISelectionTypeSelect)
DTE.ExecuteCommand("ClassViewContextMenus.ClassViewProject.Debug.Startnewinstance")
End Sub
ツールバーにボタンを追加するか、ショートカット キーを使用してこのマクロを実行できます。
ソケットが開いているかどうかを確認する手順を追加するだけです。ソケットが開いている場合は、コードの実行を続行し、ソケットが開いていないかどうかをもう一度確認してください。これにより、後で Windows サービスを開始しても問題はありません。
私が現在取り組んでいる n 層アプリケーションでは、Romil によって提案された Mutex メソッド (コードはわずかに異なりますが原理は同じです) を組み合わせ、[Conditional("DEBUG")] 属性が適用されたメソッド内にカプセル化しました (したがって、リリースモードで取り除かれます)。また、QA ビルドはデバッグ モードを使用するため、ミューテックス ロジックを if (System.Diagnostics.Debugger.IsAttached) {...} で囲みます。
当初は、ほとんどの開発者のマシンで機能する待機期間で Thread.Sleep を使用していましたが、開発者のコンピューターの速度はさまざまであり、サーバーのブートストラッパーにますます追加するにつれて、待機期間を増やし続ける必要があったため、問題が発生しました。 .
遅延を設定する引数をクライアント アプリケーションに渡してみませんか?
static void main(string[] args)
{
// Sleep some time
int delay;
if (args.Length > 0 && int.TryParse(args, out delay))
{
Thread.Sleep(delay);
}
// Initialize client
}
これで、プロジェクトの起動のコマンド ライン引数に遅延をミリ秒単位で追加できるようになりました。
また、可能であれば、問題を構造的に解決する方がよいことにも同意します。そのため、クライアントとサーバーがいつ起動するかは問題ではありません。