バックグラウンドで何らかの処理を行うWPFアプリケーションを作成しました。アプリケーションが終了すると、プロセスが終了するまでプロセスが終了するまで待つ必要があります。このコードは、フォームを閉じてアプリケーションを閉じると完全に実行されます。しかし、アプリケーションを開いたままの状態でWindowsセッションからログオフしたり、マシンを再起動すると、アプリケーションはSemaphoreSlim.Wait()で終了するようです。奇妙なことは、エラーがイベントログに記録されていないことです。 try catchでエラーをキャプチャしようとしましたが、エラーはまだキャッチされません。ここでウィンドウがログオフする前にスレッドが終了するのを待つ方法
は私のコードです:
public partial class NotifyWindow : Window
{
StreamWriter _stream;
public NotifyWindow()
{
InitializeComponent();
_stream = File.AppendText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "log.txt"));
WriteLine("startup");
}
private void WriteLine(string line)
{
var text = string.Format("{0} {1}", DateTime.Now, line);
lock (_stream)
{
_stream.WriteLine(text);
_stream.Flush();
}
}
SemaphoreSlim _locker = new SemaphoreSlim(0);
private void CloseMe()
{
WriteLine(string.Format("CloseMe started"));
Thread.Sleep(1000);
WriteLine(string.Format("release lock"));
_locker.Release();
WriteLine(string.Format("CloseMe finished"));
}
protected override void OnClosing(CancelEventArgs e)
{
WriteLine(string.Format("OnClosing started"));
base.OnClosing(e);
var t = new Thread(CloseMe);
t.Start();
WriteLine("Waiting on lock.");
_locker.Wait();
WriteLine("Waiting on lock finished.");
WriteLine(string.Format("OnClosing finished"));
}
}
これは、次のログ
When application is closed by closing the window
24-4-2017 13:57:29 startup
24-4-2017 13:57:30 OnClosing started
24-4-2017 13:57:30 Waiting on lock.
24-4-2017 13:57:30 CloseMe started
24-4-2017 13:57:31 release lock
24-4-2017 13:57:31 CloseMe finished
24-4-2017 13:57:31 Waiting on lock finished.
24-4-2017 13:57:31 OnClosing finished
When application is closed by windows logoff
24-4-2017 13:57:43 startup
24-4-2017 13:57:47 OnClosing started
24-4-2017 13:57:47 Waiting on lock.
24-4-2017 13:57:47 CloseMe started
になり、私はアプリケーションを閉じる前に終了したスレッド上でコードを待つことができます方法はありますか?私はさまざまな(How to wait for thread to finish with .NET?)スレッド待機代替を試みましたが、すべて同じ動作を示すようです。
私は、.NET 4.6.2を使用していますが、私は問題はあなたが最初base.closeを呼んでWindows 7およびWindows 10
TIA、
バート・フリース
あなたのスレッドは何をしていますか?メッセージをファイルに書き込むために使用されている場合は、ロギングライブラリまたはテキストをファイルに追加する 'ActionBlock'のいずれかで完全に置き換えることができます。アプリケーションを閉じるときや 'SessionEnding'イベントが発生したときに' ActionBlock.Complete() 'メソッドを使うことができます。結果はきれいになります –
私はActionBlockを使ってコードを書き直しました。問題は、ウィンドウからログオフするときにアプリケーションがActionBlock.Completion.Wait()で終了しない場合と同じままです(フォームを閉じても正しく待機しますが、Windowsはシャットダウンしません)。 – DesDesDes
* 'SessionEnding'で' Complete() 'を呼び出しましたか?ブロックが動作しないようにするセマフォーなどを削除しましたか? '.Wait()'を使う必要はありません。イベントハンドラのシグネチャを 'async void'に変更し、' await block.Completion; 'と書くことができます。例えば' block.Complete(); block.Completion;を待つ。 –