0

这是我的问题,我创建了一个SortableCollection:ObservableCollection 并添加了一个排序方法(排序颜色)。 当我排序与主要线程的集合,它的作品的每一件事情都很好,并且工作 但是当我尝试通过使用集合中的项目来排序此customCollection时,我有一个期望:(调用线程无法访问此对象,因为不同的线程拥有它)。 我看了网页,我发现了几种解决方案,One Solution如何创建一个observableCollection可排序和多线程

这种类型的解决方案把收集多线程插入,删除移动操作。 但不适用于自定义排序。 感谢您的帮助,

回答

0

WPF类具有线程关联性。这意味着对这些对象的所有更改必须位于创建它们的同一个线程中。创建一个线程安全的用户界面API确实很难,所以微软选择保持它的单线程并强制运行时检查以确保它。

也就是说,有几个选项需要在后台线程中执行排序,然后将其应用于UI线程中。第一个选项是将您的SortableCollection复制到一个普通的旧List或Array中,并在后台执行排序。一旦后台线程完成,您就可以使用Dispatcher在UI线程中执行代码。 WPF中的每个UI元素都延伸System.Windows.Threading.DispatcherObject,大部分延伸System.Windows.Freezable。 DispatcherObject是让Dispatcher在UI线程中执行代码的地方。

从逻辑上讲,执行将是这样的:

public void BackgroundSort() 
{ 
    List<T> items = new List<T>(this.ToArray()); 
    BackgroundSortDelegate del = Sort; 

    del.BeginInvoke(SortCompleted, del); 
} 

private void SortCompleted(IAsyncResult result) 
{ 
    BackgroundSortDelegate del = result.AsyncState as BackgroundSortDelegate; 

    List<T> items = del.EndInvoke(result); 
    this.Dispatcher.Invoke(()=>{this.Collection = items;}); 
} 

所发生的短的解释是,后台工作/委托在此列表中使用项目的副本。排序完成后,我们调用Dispatcher对象并调用一个操作。在这个动作中,我们将新的排序列表分配给我们的对象。

在UI线程内分配任何后台工作结果的关键是使用UI的Dispatcher对象。实际上可能有六种方法在C#中调用后台工作程序,但将后台线程放到UI线程中的方法是相同的。

+0

感谢Berin的解释, 但是,我必须把这种方法? 在SortableCollection中或者在处理排序方法的事件处理程序中? – Khaldoun 2010-12-21 14:21:05

+0

无论它对你来说最合理的逻辑。在SortableCollection中做这件事的好处是你可以将SortableCollection传递给不同的方法,并且它们可以自动与它进行交互。请注意警告:调度程序是一项昂贵的操作。偶尔可以调用它,但是在一个紧密的循环中它会减慢速度。 – 2010-12-21 14:38:47