如何创建 observableCollection 可排序和多线程

发布于 2024-10-08 15:00:39 字数 341 浏览 0 评论 0原文

这是我的问题,我创建了一个 SortableCollection : ObservableCollection 并添加了排序方法(排序颜色)。 当我使用主 Thread 对集合进行排序时,它可以正常工作,一切都很好 但是当我尝试使用集合中的项目对这个 customCollection 进行排序时,我有一个expetion:(调用线程无法访问该对象,因为不同的线程拥有它)。 我查看了网络,找到了几种解决方案, 一个解决方案

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

Here is my problem , I have created a SortableCollection : ObservableCollection
and added a sort method (sort colors).
When I sort The collection with the principal Thread , it works every thing is fine and works
But When I try to sort this customCollection by using an item in the collection I have an expetion : (The calling thread cannot access this object because a different thread owns it).
I have looked in web and I found several solution , One Solution

This type of solution put the collection multithread for insertion , removing moving operation.
But not for the custom sort.
Thanks for help,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

拍不死你 2024-10-15 15:00:39

WPF 类具有线程关联性。这意味着对这些对象的所有更改都必须在创建它们的同一线程中进行。创建线程安全的用户界面 API 确实很困难,因此 Microsoft 选择保持单线程并强制运行时检查来确保这一点。

也就是说,您必须使用一些选项在后台线程中执行排序,然后将其应用到 UI 线程中。第一个选项是将 SortableCollection 复制到普通的旧列表或数组中,并在后台执行排序。后台线程完成后,您可以使用 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 线程中的方法是相同的。

WPF classes have thread affinity. What this means is that all changes to those objects must be in the same thread where they were created. It truly is difficult to create a user interface API that is thread-safe, so Microsoft chose to keep it singlethreaded and force run-time checking to make sure of it.

That said, there are a few options you have to perform your sort in a background thread, and then apply it in the UI thread. The first option is to copy your SortableCollection into a plain old List or Array and perform the sort in the background. Once the background thread is complete, you use a Dispatcher to execute code in the UI thread. Every UI element in WPF extends System.Windows.Threading.DispatcherObject and most extend System.Windows.Freezable. The DispatcherObject is where you get the Dispatcher to execute code in the UI thread.

Logically, the execution would be something like this:

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;});
}

The short explanation of what happened is that the background worker/delegate is using a copy of the items in this list. Once the sort is complete, we are calling the Dispatcher object and invoking an action. In that action we are assigning the new sorted list back to our object.

The key to assigning the result of any background work within the UI thread is to use the UI's Dispatcher object. There's actually probably a half dozen ways to invoke a background worker in C#, but the approach to get your work in a background thread into the UI thread is the same.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文