我已經編寫了一個WPF應用程序,它在後臺執行一些處理。當應用程序關閉時,我想等到處理完成後才能停止進程。當我通過關閉表單關閉應用程序時,此代碼完美運行。但是,當我離開應用程序打開結束註銷我的Windows會話或重新啓動機器時,應用程序似乎終止於SemaphoreSlim.Wait()。奇怪的是事件日誌中沒有記錄錯誤。我嘗試用try catch捕獲錯誤,但錯誤仍未被捕獲。如何等待一個線程完成Windows註銷之前
這裏是我的代碼:
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和我轉載
你的線程是做什麼的?如果它用於將消息寫入文件,則可以使用日誌庫或將文本附加到文件的'ActionBlock'完全替換它。當關閉應用程序或觸發'SessionEnding'事件時,可以使用'ActionBlock.Complete()'方法。結果會更清晰 –
我用ActionBlock重寫了代碼。當我們從Windows註銷(關閉表單確實等待,但Windows關機不)時,問題仍然與ActionBlock.Completion.Wait()上未終止的應用程序相同。 – DesDesDes
*您在'SessionEnding'上調用了'Complete()'嗎?你是否刪除了信號量或其他會阻止該塊運行的東西? 您不需要使用'.Wait()',您可以將事件處理程序的簽名更改爲'async void'並寫入'await block.Completion;',例如'block.Complete();等待block.Completion;'。 –