Лучший способ запустить фоновое задание с таймером - PullRequest
0 голосов
/ 06 февраля 2019

Следующий код запускает задачу, которая каждые 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 голосов
/ 06 февраля 2019

Забудьте о Dispatcher.BeginInvoke и System.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();
}

ЕслиПредполагается, что тиковый обработчик выполняет какую-то длительную задачу, вы можете объявить ее асинхронной:

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

    // probably update UI after await
}
...