私はC#と.NET 4.0で作業しています。システムメッセージの流れを止めることなく、フロントエンドが長いプロセスを待つ方法が必要です
私のプログラムは、フロントエンドとバックエンドで構成されています。バックエンドは、システムの起動時に自動的に起動するWindowsサービスとして実行されます。フロントエンドは、アプリケーションを使用する準備ができたときにユーザーが開始するWPFアプリケーションです。
スタートアッププロセスの一部として、フロントエンドはバックエンドとの通信を確立する必要があります。これはXMPPを使用して行われ、正常に動作します。通信を行うコードには、WaitHandleを返すBeginStartメソッドがあります。 try-catchの中で、私はBeginStartを呼び出し、WaitHandleを取得し、WaithandleのWaitOne(TimeSpan)メソッドを呼び出します。この時点でプログラムはスプラッシュスクリーンを表示していることに注意してください。そして、これらの呼び出しはフロントエンドスレッドで行われています。
これは正常に動作していますが、WaitOneコールの実行中に他のウィンドウをクリックしても効果はありません。基本的に、すべてのWindowsメッセージトラフィックは、このWaitHandleが戻るのを待って停止します。
私はBeginStartとWaitOneの呼び出しを別のスレッドで行う必要があると思います。 WaitOne呼び出しが正常に返されない限り(タイムアウトなし)、プログラムが終了し、ユーザーインターフェイスが表示されないため、WaitOneが戻るのを待つためにフロントエンドが必要です。他のプログラムがWindowsメッセージを処理できるようにするだけです。
この作品を作成するにはどうすればよいですか? WPFにはApplication.DoEventsメソッドはありません。
トニー
は編集:
私はいくつかのより多くの情報を提供する場合、それは役に立つかもしれように見えます。
私のWPFアプリケーションは、この製品のユーザーインターフェイスであり、製品全体の半分のみを構成します。残りの半分は同じPC上でWindowsサービスとして実行されており、バックエンドと呼んでいます。バックエンドで何が起こっているかは、XMPPを使用して接続をリスンしていることを除いて、重要ではありません。
ユーザーインターフェイス(またはフロントエンド)が起動すると、XMPPを使用してバックエンドとの通信を確立する必要があります。これは通常最大で2〜2回かかります。ただし、ユーザーがフロントエンドを起動したときに何か問題が発生したり、バックエンドが停止したりする可能性があります。私はフロントエンドが無期限に待つことを望まない。それは合理的な時間の後にタイムアウトし、エラーメッセージを表示して死ぬ必要があります。
通信を確立するには、別のスレッドとして起動するモジュールがあります。私はWaitHandleを返すBeginStartメソッドを呼び出しています。私はWaitHandleを待ち、TimeSpanをタイムアウト期間に渡します。スニペットは次のとおりです。
try {
WaitHandle handle = BackgroundProcess.BeginStart();
if (!handle.WaitOne(Timeout)) {
// Something went wrong; Notify user here
return false;
}
// Make sure that the Background Process has started all of it's internal modules
bool allAreRunning;
Stopwatch timer = new Stopwatch();
timer.Reset(); timer.Start();
do {
allAreRunning = true;
foreach (Module module in BackgroundProcess.Modules) {
if (module.State != Module.States.Running) {
allAreRunning = false;
break;
}
}
if (!allAreRunning) {
// I hate this loop, but I can't think of a better way to do this
Thread.Sleep(1000);
}
} while (!allAreRunning && timer.ElapsedMilliseconds <= Timeout.TotalMilliseconds);
timer.Stop();
if (!allAreRunning) {
// Something went wrong; Notify user here
return false;
}
// Other initialization done here
} catch (Exception ex) {
// Something went wrong; Notify user here
return false;
}
これをテストするには、バックエンドがダウンしている間にデバッガでプログラムを実行してください。私は開いているウィンドウをクリックしてそれに切り替え、それとうまくやりとりすることができます。私ができないことは、デスクトップをクリックすることです。 WaitHandle.WaitOne()呼び出しは非常に迅速に戻ります。バックグラウンドプロセスの実行が開始され、接続が確立されるのを待たずに戻ります。これは、ほとんどのタイムアウト期間に実行されるdo-whileループです。
これを書き直す必要があるため、ユーザーはプログラムを開くだけでなく、デスクトップをクリックすることもできます。私はちょうどそれを動作させる方法を知らない。
トニー
プログラムは、システム上の他のすべてのプログラムをブロックしてはならないワン:
コードは次のようになります。コードスニペットを投稿できますか? –