代码之家  ›  专栏  ›  技术社区  ›  scharette

在关闭WPF应用程序时处理将更改应用到UI线程的计时器

  •  0
  • scharette  · 技术社区  · 6 年前

    考虑一个计时器,它将在WPF应用程序中的单击事件上触发,如下所示,

    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        Timer t = new Timer(DoingWorkOnUI,null,0,5000);
    
        //Also doing long execution time job here. in another thread
    }
    

    基本上,问题是如果用户关闭应用程序,我的计时器仍在运行,并且从未关闭,导致 任务已取消 错误我想在他的回访中处理,但我不知道该怎么做。

    这是我的尝试,我可能完全错了,但我能很好地捕捉到取消,我只是找不到如何处理计时器的解决方案。

    private void DoingWorkOnUI(object state) {
        cts = new CancellationTokenSource();
        var token = cts.Token;
        try
        {
            token.ThrowIfCancellationRequested();
            this.Dispatcher.Invoke((Action)(() =>
            {
                \\Doing work on UI
            }));
        }
        catch (OperationCanceledException)
        {
            //Dispose Timer here ???
        }
        finally {
            //Disposing token
            cts.Dispose();
        }
    }
    
    1 回复  |  直到 6 年前
        1
  •  0
  •   mm8    6 年前

    你可以处理 Closing 处理计时器的窗口事件。

    因为您正在创建 IDisposable 字段,您还应该实现 dispose pattern 为了符合最佳实践指南:

    public partial class MainWindow : Window, IDisposable
    {
        private Timer _t;
    
        public MainWindow()
        {
            Closing += OnClosing;
        }
    
        private void OnClosing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            Dispose(true);
        }
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            if(_t != null)
                _t.Dispose();
    
            _t = new Timer(DoingWork, null, 0, 5000);
        }
    
        private void DoingWork(object state)
        {
            //....
        }
    
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    
        protected virtual void Dispose(bool disposing)
        {
            if (disposing && _t != null)
                _t.Dispose();
        }
    }