正确的方式来不断更新UI

时间:2017-05-31 13:04:03

标签: c# wpf xaml

假设客户端应用程序几乎实时从服务器获取数据。基于检索到的数据持续更新UI的更有效方法是什么。想想多个xaml控件,比如显示数字的文本。只要应用程序正在运行,它们就会更新。除非用户决定,否则他们永远不会停止。 (让我们通过按停止按钮或退出应用程序说) 下面我有一个使用async和await关键字的简单示例。这对我的情景来说是一个好方法吗?或者例如BackgroundWorker会是一种更好的方法吗?

private async void Button_Click_Begin_RT_Update(object sender, RoutedEventArgs e)
{
    while(true)
        textField1.Text = await DoWork();
}

Task<string> DoWork()
{
    return Task.Run(() =>
    {
        return GetRandomNumberAsString();
    });
}

*为了简单起见,我在我的示例中使用了代码隐藏而不是mvvm

1 个答案:

答案 0 :(得分:2)

如果GetRandomNumberAsString()完成至少需要15毫秒,那么您的代码或多或少都可以。

如果它花费的时间少于此,并且您希望最小化更新延迟,即您不想等待,您可能希望(1)用无限循环替换每个操作Task.Run完全在后台线程中运行(2)在该循环中实现限制机制,并且仅在30-60Hz左右更新GUI(使用例如Dispatcher.BeginInvoke())。

P.S。更新GUI(数据绑定+ INotifyPropertyChanged,或直接在代码中更新)的确切机制与性能无关。

更新:此处的示例(未经测试)

static readonly TimeSpan updateFrequency = TimeSpan.FromMilliseconds( 20 );
void ThreadProc()
{
    Stopwatch sw = Stopwatch.StartNew();
    while( true )
    {
        string val = GetRandomNumberAsString();
        if( sw.Elapsed < updateFrequency )
            continue;   // Too early to update
        sw.Restart();
        Application.Current.Dispatcher.BeginInvoke( () => { textField1.Text = val; } );
    }
}