头脑风暴:如何在Silverlight中实现后台计算?
我目前正在开发一个 Silverlight 4.0 应用程序,该应用程序在 da DataGrid 控件中显示大约 13.000 行。单个项目包含大约 40 个字符串属性和一个整数属性。
在包含该网格的页面上是一个面板,用户可以在其中设置不同的权重。单击“更新”按钮后,Silverlight 应根据该设置进行一些计算。
在计算过程中,大量使用反射(并且是必要的)来获取 String 属性的值。最后计算出分数并将其写入整数字段。需要对 13,000 个对象中的每一个对象执行此操作。
目前,作为临时解决方案,我使用 BackgroundWorker
实例和 Grids Dispatcher(进入 UI 线程并允许访问 Grid 的 ItemsSource 属性),迭代每个项目并计算分数。 此过程大约需要 3 分钟,而且时间太长,因为用户不想等待超过几秒钟。不幸的是PLinq & Co 不包含在 Silverlight 4 中,甚至我尝试为此实现多线程解决方案也失败了,因为我需要回退到 UI 线程(->Dispatcher)来更新每个元素(实现 INotifyPropertyChanged< /code> 转发到网格)并访问 ItemsSource。因此,即使使用半并行解决方案,由于对 UI 线程的依赖,速度也不是很快。
除了仅显示数据之外,用户还需要能够过滤默认情况下不支持的数据。因此,我创建了一个类似于这个的类,它实现了ICollectionView< /代码> 接口。
你有什么想法或建议我可以尝试吗?
提前致谢!
I am currently working on a Silverlight 4.0 Application that displays about 13.000 rows in da DataGrid control. A single item contains about 40 String properties and one integer one.
On the page that contains that Grid is a panel where the user can set different weightings. After clicking on an "Update" button Silverlight should do some calculations depending on that settings.
During the calculation reflection is heavily used (and necessary) to get the values of the String properties. Finally as a result a score is calculated and written to the integer field. This needs to be done for every single of the 13.000 objects.
Currently, as a temporary solution, I use a BackgroundWorker
instance and the Grids Dispatcher (to get into the UI thread and to be allowed to access the ItemsSource property of the Grid), iterate over each item and calculate the score.
This process needs about 3 minutes and is way too long as the user doesn't want to wait more than a few seconds. Unfortunately PLinq & Co are not included in Silverlight 4, and even my try to implement a multi-threaded solution for this failed because I need to fall back to the UI Thread (->Dispatcher) to update each element (that implements INotifyPropertyChanged
which is forwarded to the Grid) and to access the ItemsSource. So even when using a semi-parallel solution it isn't really fast because of the dependence on the UI Thread.
Additional to just displaying the data the user needs to be able to filter the data which is not supported by default. Therefore I created a class similar to this one that implements the ICollectionView
interface.
Do you have any idea or suggestion what I could try?
Thanks in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我的建议是不要对相关对象使用
INotifyPropertyChanged
或使用ObservableCollection
。相反,使用一个简单的类来表示一行,并使用普通的旧List
来保存集合。使用CollectionViewSource
对象作为DataGrid.ItemsSource
并让它处理排序。重新计算时请先尝试此操作。切换到后台线程。创建一个新的
List
,将其容量初始化为与当前填充的List
计数相同。枚举当前的List
以执行重新计算,然后添加到新的List
中。处理完所有内容后,切换到 UI 线程,并将新的List
分配给CollectionViewSource.Source
属性。我怀疑这一更改将使事情变得足够快,而无需编写列表的任何并行处理。然而,如果您认为包含一些并行处理会有所帮助,那么它应该太难了。这种方法的一大优点是,只有当所有操作完成后,UI 才会更新。
My suggestion is don't use
INotifyPropertyChanged
on the objects in question or use anObservableCollection<T>
. Instead use a simple class to represent a row and plain oldList<T>
to hold the set. Use aCollectionViewSource
object as theDataGrid.ItemsSource
and let that handle sorting.When recalculating try this first. Switch to a background thread. Create a new
List<T>
initialising its capacity to the same as the currently populatedList<T>
count. Enumerate the currentList<T>
to perform recalculations and then add into the newList<T>
. When all are processed switch to the UI thread and simply assign the newList<T>
to theCollectionViewSource.Source
property.I suspect that this change will make things plenty quick enough without any need to write any parrallel processing of the list. However it should be too hard to include some parrallel processing if you feel that would help. The big advantage of this approach is that the UI is updated only when all is done.