【问题标题】:C# WPF Dispatcher Timer Tick in Separate ThreadC# WPF Dispatcher Timer Tick 在单独的线程中
【发布时间】:2020-05-20 09:48:50
【问题描述】:

所以我有一个基本的 WPF 应用程序,OnStartup 创建一个 DispatcherTimer 并有一个 tick 方法,它运行基本的 SQL 查询来检查任意表的状态。

就执行时间而言,这是一个变量查询。

如果我在主应用程序窗口中,当后台 DispatcherTimer 运行时(DispatcherTimer 代码在 App.xaml 内,而不是 MainWindow.xaml),窗口在查询运行时挂起,并且作为查询每 5 秒运行一次,GUI 无响应。

似乎一个新线程是要走的路,但我不知道从哪里开始。我对 C#/WPF 比较陌生,所以目前这只是一个学习曲线。我将如何在一个新线程中调用我的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;

    }

【问题讨论】:

    标签: c# wpf multithreading


    【解决方案1】:

    使 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;
    }
    

    直接调用异步方法更好,比如

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

    【讨论】:

    • 完美,谢谢!等待命令也是如此。 ExecuteReaderAsync();本质上是在另一个线程中运行 SQL 查询?
    • 不确定它是否是一个单独的线程 - 这实际上并不重要。许多文件 I/O 调用本质上是异步的,不需要线程。
    • 但是这里长时间运行的查询不会阻止 MainWindow.xaml 响应?即它会防止挂起?
    • 没问题,试一试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-17
    相关资源
    最近更新 更多