运行 带计时器的后台任务的最佳方式

Best way to run a background task with timer

以下代码运行 一个任务,每 5 秒检查一次数据库的状态。我不得不使用 BeginInvoke,但我不确定这是最好的方法:

public btnDatabaseStatus()
{
    InitializeComponent();

    if (!DesignerProperties.GetIsInDesignMode(this))
        Global.LM.SetTraduzioniWindow(this);                        
    Init();

    DispatcherOperation dbStatDispatcher = null;
    try
    {
        dbStatDispatcher = App.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
        {
            Timer timer = new Timer(5000);
            timer.Elapsed += OnTimedEvent;
            timer.Enabled = true;
        }));
    }
    catch (Exception ex)
    {
        if (dbStatDispatcher != null) dbStatDispatcher.Abort();
    }
}

private void OnTimedEvent(object source, ElapsedEventArgs e)
{
    if (App.Current!=null) App.Current.Dispatcher.BeginInvoke(new Action(() => { IsDbConnected = Dbs[0].IsConnected; }));
}

private void Init()
{
    Dbs = null;
    Dbs = Global.DBM.DB.Values.Where(d => d.IsExternalDB).ToList();
    lstvDatabase.ItemsSource = Dbs;
}

我担心主应用程序的关闭,因为有时 Dispatcher 为空。有任何改进代码的提示吗?

忘记 Dispatcher.BeginInvokeSystem.Threading.Timer

使用 WPF DispatcherTimer:

public btnDatabaseStatus()
{
    InitializeComponent();

    var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(5) };
    timer.Tick += OnTimerTick;
    timer.Start();
}

private void OnTimerTick(object sender, EventArgs e)
{
    IsDbConnected = Dbs[0].IsConnected;
}

或更短:

public btnDatabaseStatus()
{
    InitializeComponent();

    var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(5) };
    timer.Tick += (s, e) => IsDbConnected = Dbs[0].IsConnected;
    timer.Start();
}

如果 Tick 处理程序应该执行一些长 运行 任务,您可以将其声明为异步:

private async void OnTimerTick(object sender, EventArgs e)
{
    await SomeLongRunningMethod();

    // probably update UI after await
}