簡體   English   中英

如何在Windows注銷之前等待線程完成

[英]How can I wait on a thread to finish before windows logoff

我編寫了一個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

有沒有辦法可以在關閉應用程序之前等待線程上的代碼完成? 我嘗試了各種( 如何等待.NET完成線程? )線程等待替代方案,但似乎都表現出相同的行為。

我正在使用.net 4.6.2,並且在Windows 7和Windows 10上重現了該問題。

TIA,

巴特·弗里斯

當用戶通過注銷或關閉操作系統來結束Windows會話時,將發生Application.SessionEnding事件。 您可以嘗試處理此問題。

您的應用程序實際上無法控制操作系統的作用。 用戶可能仍會在您的代碼確定之前終止您的應用程序,恐怕您對此無能為力。

問題是您首先在事件關閉中調用base.close,您應該取消窗體的關閉。在線程作業完成后,您調用this.close,但是這次您將參數exit設置為true(定義參數)

謝謝大家的反饋。 根據您的反饋,我找到了不使用任何操作系統鎖定機制的解決方法。 這似乎正在工作。

這是代碼:

public partial class NotifyWindow : Window
{
  StreamWriter _stream;
  volatile int _running = 0;

  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();
    }
  }

  private void CloseMe()
  {
    WriteLine(string.Format("CloseMe started"));
    Thread.Sleep(1000);

    WriteLine(string.Format("release lock"));
    _running = 1;

    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.");

    while(_running == 0)
    {
      Thread.Sleep(50);
      WriteLine("Waiting for 50ms.");
    }

    WriteLine("Waiting on lock finished.");

    WriteLine(string.Format("OnClosing finished"));
  }
}

謝謝大家的幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM