简体   繁体   English

C# WPF Dispatcher Timer Tick 在单独的线程中

[英]C# WPF Dispatcher Timer Tick in Separate Thread

So I have a basic WPF application, that OnStartup creates a DispatcherTimer and has a tick method that runs a basic SQL query to check the status of some arbitrary table.所以我有一个基本的 WPF 应用程序,它OnStartup创建一个DispatcherTimer并有一个运行基本 SQL 查询的滴答方法来检查一些任意表的状态。

It is a variable query in terms of how long it takes to execute.就执行所需的时间而言,这是一个可变查询。

If I am in the main application window, when the background DispatcherTimer runs ( DispatcherTimer code being within the App.xaml , not the MainWindow.xaml ), the window hangs while the query runs, and as the query runs every 5 seconds, the GUI is unresponsive. If I am in the main application window, when the background DispatcherTimer runs ( DispatcherTimer code being within the App.xaml , not the MainWindow.xaml ), the window hangs while the query runs, and as the query runs every 5 seconds, the GUI没有反应。

It seems a new thread is the way to go, but I am lost on where to begin.似乎一个新线程是通往 go 的方式,但我不知道从哪里开始。 I am relatively new to C#/WPF so it's all a learning curve at the moment.我对 C#/WPF 比较陌生,所以目前这只是一个学习曲线。 How would I go about invoking my dispatcherTimer_Tick within a new thread, to avoid this problem?我将如何 go 在新线程中调用我的dispatcherTimer_Tick以避免这个问题?

DispatcherTimer dispatcherTimer;

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        MainWindow = new MainWindow();
        MainWindow.Closing += MainWindow_Closing;

        _notifyIcon = new System.Windows.Forms.NotifyIcon();
        _notifyIcon.DoubleClick += (s, args) => ShowMainWindow();
        _notifyIcon.Icon = BackgroundApplication.Properties.Resources.GTL;
        _notifyIcon.Visible = true;

        CreateContextMenu();

        dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
        dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
        dispatcherTimer.Interval = new TimeSpan(0, 0, 5);
        dispatcherTimer.Start();

    }

    private void dispatcherTimer_Tick(object sender, EventArgs e)
    {
        // Console.WriteLine("Tick");

        SqlConnection cnn;
        connectionString = @"SOME_DATA_SOURCE";
        cnn = new SqlConnection(connectionString);
        cnn.Open();
        // MessageBox.Show("Connection Open  !");
        // cnn.Close();

        SqlCommand command;
        SqlDataReader dataReader;
        String sql = "";
        Int16 output = 0;

        sql = "SOME SQL STATEMENT";
        command = new SqlCommand(sql, cnn);
        dataReader = command.ExecuteReader();

        while (dataReader.Read())
        {
            output = Int16.Parse(dataReader[""].ToString());
        }

        if(output > 0)
        {
            _notifyIcon.Icon = BackgroundApplication.Properties.Resources.RTL;  

        }

        _notifyIcon.Text = "Current Issues: " + output;

    }

Make the Tick handler async and await the long-running call:使 Tick 处理程序异步并等待长时间运行的调用:

private async void dispatcherTimer_Tick(object sender, EventArgs e)
{
    await Task.Run(() =>
    {
        // make query here
    });

    // update the UI outside the Task
    _notifyIcon.Text = "Current Issues: " + output;
}

Even better would be to directly call async methods, like更好的是直接调用异步方法,比如

private async void dispatcherTimer_Tick(object sender, EventArgs e)
{
    ...
    dataReader = await command.ExecuteReaderAsync();
    ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM