我正在使用Silverlight 5.0并需要实现IList<T>
和IList。我的集合将用于不断添加和删除其内部集合中的项目,并且UI将具有绑定到集合的元素。出于性能方面的原因,我不希望UI在每次更改集合时都进行渲染,因为我希望对集合进行“组”更改,然后引发集合更改事件。我也希望能够使用Task.Factory方法来完成这一切,以保持一切异步。有没有人看到如何实现这一目标的好例子?异步,线程安全的集合实现INotifyCollectionChanged
回答
线程安全的可观察集合在设计上存在问题。例如,如果更改集合并引发事件,则在处理该事件时,可以在另一个线程上更改集合。结果,刚刚被告知某个物品的处理程序已经过期(该物品可能已经不存在了)。
或者,您是否考虑在集合更改时使用带有事件的immutable collection?它本质上是线程安全的,如果正确应用它,不会受到上述设计问题的困扰。它可能不符合你对这个应用程序的要求 - 从这个问题很难说。
处理程序可能在过期后调用的事实不应被视为问题。处理程序处理这些事情并不困难,并且没有理由不应该为他们准备一个体面的处理程序。更大的问题是当事件处理程序已经运行时,可能会将某些内容添加到集合中。通常,调用SomeCollection.Add的代码有权假定所有事件处理程序在返回之前都会触发,但强加此类语义会造成死锁的可能性。 – supercat 2012-12-31 20:00:52
我建议的方法是为可能需要更新UI的集合的不同方面设置各种标志。如果集合中的某些内容发生更改并且未设置特定的标志,请设置它并在提供的控件和委托上使用Control.BeginInvoke
(使用Interlocked
或锁定以确保标志测试和设置是以线程安全的方式完成的) 。 UI更新方法应该在执行更新之前测试并清除相应的标志;如果执行了任何更新,该方法应循环并重新测试所有标志,直到完成而不必执行任何更新。
使用这种方法,应该能够避免通过BeginUpdate
排队的过多数量的挂起操作。可能会有一些重复的更新,但通常不会太多。在某些情况下,让控件的代码限制每秒执行的更新次数可能会有所帮助;如果更新例程将循环太多次,则启动一个定时器并禁用更新,直到定时器到期。如果定时器到期并需要更新,请执行更新并重新启动定时器;如果过期并且不需要更新,则取消定时器。
试图对集合进行每一次更改都会反映在“更新”事件中,这样做容易起反作用。只要确保显示的最后一次更新完全发生在集合的最后一次更改之后。
- 1. 链接线程安全集合线程安全吗?
- 2. 异步文件IO线程安全吗?
- 3. 线程安全异步字节队列
- 4. 线程安全的找到并集合
- 5. .NET中的线程安全集合
- 6. 线程安全VS异步信号安全
- 7. .NET 2.0:File.AppendAllText(...) - 线程安全的实现
- 8. 实现'线程安全的'链表
- 9. 成员集合迭代线程安全
- 10. IStorage的复合文件实现是线程安全的吗?
- 11. 存储在线程安全集合线程中的对象是否安全?
- 12. 线程安全日志类实现
- 13. 是LinkedList实现.Net线程安全吗?
- 14. NSThread线程安全实现初始化。
- 15. 如何在使用集合时实现线程安全缓存机制?
- 16. 使用线程安全集合的多个线程
- 17. 在异步任务和redis的django中的线程安全
- 18. C++中的异步线程安全日志记录
- 19. 如何使使用队列线程安全的异步方法
- 20. 同步vs线程安全集合vs原子包装类vs锁
- 21. .NET异步套接字超时检查线程安全
- 22. TPL异步静态方法调用线程安全
- 23. 跟踪异步加载与线程安全吗?
- 24. 线程安全异步非重入任务
- 25. 异步线程
- 26. 使用C++中的futures,异步和线程实现搜索11
- 27. 如何实现一个真正的异步Java线程
- 28. 安全地同步COM线程
- 29. 为线程安全同步NSMutableArray?
- 30. 线程安全的数据集
Caliburn Micro拥有一个可以关闭和打开的IsNotifying属性的Bindable集合。我没有在多线程互斥环境中使用它。但是,这是值得一试的。 – Jeremiah 2012-03-13 21:05:09