9

我的申请有点问题。
我想每 10 秒更新一次我的 UI 上的内容。我首先DispatcherTimer为此使用了 a ,但它会在短时间内阻塞我的 UI,因为更新方法需要从 Web 加载某些内容,并且此操作需要一些时间。现在我想到了某种后台工作者,然后我找到了 BackgroundTasks。
后台任务的问题在于,据我正确理解,即使应用程序被挂起,它们也应该充当更新程序。我不需要那个。我只想在我的应用程序正在运行时更新,而不是在它被暂停时更新。

有没有解决这个问题的好方法?有什么建议可以用这个吗?

提前致谢!

4

4 回答 4

12

你需要两件事:

  1. 定时器

    System.Timers.Timer您可以每隔 10 秒更新一次 UI 。

  2. 调度员

    您需要使用Dispatcher.Invoke更改 UI 而不持有主 UI 线程。相反,该方法Process应该在一个单独的线程Timer方法)上调用,而不是主 UI 线程,并Dispatcher在其中使用它来提醒主 UI 线程进行更改。

    Process() // method to be called after regular interval in Timer
    {
        // lengthy process, i.e. data fetching and processing etc.
    
        // here comes the UI update part
        Dispatcher.Invoke((Action)delegate() { /* update UI */ });
    }
    
于 2012-11-24T00:44:28.110 回答
1

您需要创建一个线程来运行从网站获取和处理信息的代码部分。这样,您的表单将不会犹豫,因为它将位于与处理部分不同的线程上。

这篇关于代码项目的文章应该可以帮助您入门。

于 2012-11-24T00:20:01.167 回答
0

其他答案缺少适当的清理:当计时器在窗口关闭的那一刻触发时,我会在尝试运行时收到未捕获的 TaskCanceledException Dispatcher.Invoke。我没有在其他问题中找到解决此问题的帮助。我能够通过在关闭窗口时取消注册计时器回调来解决它。

public partial class MainWindow : Window
{
    Timer clockTimer = null;
    public MainWindow()
    {
        clockTimer = new Timer(1.0); // 1 ms update to test for TaskCanceledException 
        clockTimer.Elapsed += Timer_Elapsed;
        clockTimer.AutoReset = true;
        clockTimer.Start();
        Closed += (object sender, EventArgs e) => { clockTimer.Elapsed -= Timer_Elapsed; };
    }
    private void Timer_Elapsed(object sender, ElapsedEventArgs e) {
        var now = DateTime.Now;
        Dispatcher.Invoke((Action)delegate () {
            UpdateTime(now);
        });
    }
}

如果重新显示窗口,显然这不是一个好主意。我尝试添加一个 dtor,但它永远不会被调用,可能是由于循环依赖。

免责声明:我不懂 C#,所以这可能不是最好或正确的做事方式。

于 2020-02-01T14:47:42.140 回答
-1

此外,您可以启动一个计时器,该计时器具有经过的事件,每次计时器经过某个时间周期时都会发生该事件。

  1. http://www.dotnetperls.com/timer
于 2012-11-24T00:19:43.923 回答