Wpf 使用多个线程频繁更新UI控件

Wpf 使用多个线程频繁更新UI控件,wpf,binding,Wpf,Binding,我有一个DevExpress GridControl单向绑定到viewmodel中的tableview。大约有20个后台线程从数据库查询数据,并分别更新tableview。表视图的更新由异步更新的锁进行保护。Dispatcher用于刷新主UI线程。我还有另一个按钮来取消数据库并通过CancellationTokenSource更新函数 但是,当应用程序运行时,我必须多次单击取消按钮才能执行cancel命令中的代码。换句话说,UI主线程正忙于刷新GridControl,它会阻止Cancel按钮 有

我有一个DevExpress GridControl单向绑定到viewmodel中的tableview。大约有20个后台线程从数据库查询数据,并分别更新tableview。表视图的更新由异步更新的锁进行保护。Dispatcher用于刷新主UI线程。我还有另一个按钮来取消数据库并通过CancellationTokenSource更新函数

但是,当应用程序运行时,我必须多次单击取消按钮才能执行cancel命令中的代码。换句话说,UI主线程正忙于刷新GridControl,它会阻止Cancel按钮

有没有办法实现这个功能

编辑:发现此方法有助于等待Dispatcher.Yield(DispatcherPriority.ApplicationIdle)的大量操作; 它只是给其他UI控件一个执行的机会

创建一个可等待的对象,该对象异步将控制权返回给当前调度程序,并为调度程序提供处理其他事件的机会。(MSDN)


好的,UI代表用户界面,其中主要部分是用户界面用户不是机器人,而是使用您的应用程序的人。您不需要在UI线程上如此频繁地查询数据更新。为什么数据库查询操作需要20个线程?您有一个GridControl,它一次只能在屏幕上显示几行,20行、50行、100行(不再显示)。所以,我建议您只使用一个线程从数据库中读取数据,并且每2-5秒执行一次,以便为用户提供一些交互性。因此,-是一个不错的选择。将它与-一起使用是支持场景取消的好方法。在数据库查询之间,可以执行以下操作:

while (true)
{
    myToken.ThrowIfCancellationRequested();
    // database query here

    myToken.WaitHandle.WaitOne(2000)
}
GridControl.BeginDataUpdate();
//Update your source collection
GridControl.EndDataUpdate();
此外,在更新源集合之前,可以使用以下选项:

while (true)
{
    myToken.ThrowIfCancellationRequested();
    // database query here

    myToken.WaitHandle.WaitOne(2000)
}
GridControl.BeginDataUpdate();
//Update your source collection
GridControl.EndDataUpdate();
这将阻止DevExpress控件侦听事件或任何其他事件,因为在每个添加/删除操作上,DevExpress调用方法的速度并没有我们希望的那么快

如果布局在这两方面都无效,UpdateLayout调用将重做整个布局。因此,您应该避免在元素树中的每次增量和微小更改之后调用UpdateLayout


当UI线程忙时,它就忙。也许您可以更高效地更新数据绑定数据收集?也许只是更新更改,而不是每次更新整个集合?我需要查询很多数据库,所以我并行查询它们以提高速度。如果我更新viewmodel中的数据,我如何调用BeginDataUpdate/EndDataUpdate?您需要将GridControl传递给您的viewmodel,这很简单,但您可以说它打破了您的MVVM模式(向DevExpress问好)。另一种方法是停止引发集合和集合元素的CollectionChanged和PropertyChanged事件,并且仅在更新周期结束时才进行,引发重置事件(有点烦人,但您的MVVM ism会得到满足)。另外,您还有更多其他选项来保存松散耦合的V和VM,但这是另一个安静的选项,这是为了“while(myToken.WaitHandle.WaitOne(2000))”是的,我错了。请稍等,您将看到编辑。是的,谢谢您的建议,但是我们需要阻止线程2秒钟吗?