使用计时器运行后台任务的最佳方法

时间:2019-02-06 17:22:55

标签: c# wpf begininvoke

以下代码运行一个任务,该任务每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为空,所以担心关闭主应用程序。有任何改进代码的提示吗?

1 个答案:

答案 0 :(得分:0)

忘记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
}