백그라운드에서 처리중인 WPF 응용 프로그램을 작성했습니다. 응용 프로그램이 닫히면 프로세스가 끝나기 전에 처리가 끝날 때까지 기다리고 싶습니다. 이 코드는 폼을 닫아 응용 프로그램을 닫을 때 완벽하게 실행됩니다. 그러나 응용 프로그램을 열린 상태로 유지하여 Windows 세션에서 로그 오프하거나 시스템을 재부팅하면 응용 프로그램이 SemaphoreSlim.Wait()에서 종료 된 것처럼 보입니다. 이상한 것은 이벤트 로그에 기록 된 오류가 없다는 것입니다. 시도 잡기로 오류 캡처를 시도했지만 오류가 여전히 잡히지 않습니다.Windows 로그 오프 전에 스레드가 완료 될 때까지 기다릴 수있는 방법
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
내가 응용 프로그램을 닫기 전에 완료 스레드에서 코드를 기다릴 수있는 방법이있는 다음 로그에
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"));
}
}
이 결과 : 여기
내 코드? 나는 다양한 (How to wait for thread to finish with .NET?) 스레드 대기 대안을 시도했지만 모두 동일한 동작을 나타내는 것처럼 보입니다.
나는 그물 4.6.2를 사용하고 난
이
스레드의 기능은 무엇입니까? 파일에 메시지를 쓰는 데 사용되는 경우, 로깅 라이브러리 또는 텍스트를 파일에 추가하는'ActionBlock'으로 완전히 바꿀 수 있습니다. 응용 프로그램을 닫거나'SessionEnding' 이벤트가 발생하면'ActionBlock.Complete()'메소드를 사용할 수 있습니다. 결과는 훨씬 더 깨끗합니다. –
ActionBlock을 사용하여 코드를 다시 작성했습니다. 문제는 응용 프로그램이 ActionBlock.Completion.Wait()에서 종료되지 않는 것과 동일하게 유지됩니다. 우리가 Windows에서 로그 오프 할 때 (폼을 닫으면 올바르게 대기하지만 Windows가 종료되지 않습니다). – DesDesDes
*'SessionEnding'에서'Complete()'를 호출 했습니까? 블록이 작동하지 못하게하는 세마포어 또는 다른 것을 제거 했습니까? '.Wait()'을 사용할 필요가 없으므로 이벤트 처리기의 서명을 async void로 변경하고'await block.Completion;','block.Complete(); 블록을 기다리고 있습니다. 완료. '. –