ObservableCollection 和线程

发布于 2024-08-22 06:57:31 字数 275 浏览 10 评论 0原文

我的班级中有一个 ObservableCollection 。在我的课堂上,我有一个话题。我想从这个线程添加到我的 ObservableCollection 中。但我不能这样做:

这种类型的 CollectionView 不支持从与 Dispatcher 线程不同的线程更改其 SourceCollection。

请注意,这不是在 UI 线程中发生的,因此我无权访问调度程序。

I have an ObservableCollection in my class. And further into my class I have a thread. From this thread I would like to add to my ObservableCollection. But I can't do this:

This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread.

Note that this is not happening from the UI thread, so i don't have access to the dispatcher.

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

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

发布评论

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

评论(3

找回味觉 2024-08-29 06:57:31

JaredPar 的方法是有效的。另一种值得考虑的方法是使用线程安全的 ObservableCollection 而不是内置的 ObservableCollection。有一些实现,但是 Sasha Barber 的实现CLinq Continuous Collection 类 在我看来是一些更好的类。在内部,这些类本质上使用 JaredPar 概述的方法,但将其封装在集合类中。

JaredPar's approach is a valid one. Another approach which is worth considering is using a thread safe ObservableCollection instead of the built-in ObservableCollection. There's a few implementations out there, but Sasha Barber's implementation and the CLinq Continuous Collection class are some of the better ones in my opinion. Internally, these classes essentially use the approach outlined by JaredPar, but encapsulate it inside the collection class.

打小就很酷 2024-08-29 06:57:31

解决此问题的最佳方法是将 Dispatcher 对象传递给后台线程的 start 方法。

void DoBackgroundOperation(ObservableCollection<SomeType> col) {
  var dispatcher = Dispatcher.CurrentDispatcher;
  ThreadStart start = () => BackgroundStart(dispatcher, col);
  var t = new Thread(start);
  t.Start();
}

private static void BackgroundStart(
    Dispatcher dispatcher, 
    ObservableCollection<SomeType> col) {
  ...
  SomeType t = GetSomeTypeObject();
  Action del = () => col.Add(t);
  dispatcher.Invoke(del);
}

现在,稍后当您需要添加到集合时,您可以使用 UI Dispatcher 对象。

正如 @Reed 指出的,更通用的解决方案是通过使用 SynchronizationContext 实现的。以下是使用 SynchronizationContext 创建负责添加新值的委托的函数样式示例。这样做的优点是从创建对象的代码中隐藏集合和线程模型。

void DoBackgroundOperation(ObservableCollection<SomeType> col) {
  var context = SynchronizationContext.Current;
  Action<SomeType> addFunc = (SomeType st) => context.Send(() => col.Add(st), null);
  ThreadStart start = () => BackgroundStart(addFunc);
  var t = new Thread(start);
  t.Start();
}

private static void BackgroundStart(Action<SomeType> addFunc) {
  ...
  SomeType t = GetSomeTypeObject();
  addFunc(t);
}

The best way to solve this is to pass the Dispatcher object to the start method of the background thread.

void DoBackgroundOperation(ObservableCollection<SomeType> col) {
  var dispatcher = Dispatcher.CurrentDispatcher;
  ThreadStart start = () => BackgroundStart(dispatcher, col);
  var t = new Thread(start);
  t.Start();
}

private static void BackgroundStart(
    Dispatcher dispatcher, 
    ObservableCollection<SomeType> col) {
  ...
  SomeType t = GetSomeTypeObject();
  Action del = () => col.Add(t);
  dispatcher.Invoke(del);
}

Now later on when you need to add to the collection you can use the UI Dispatcher object.

As @Reed pointed out, a more general solution is achieved by using SynchronizationContext. Here's a functional style sample using SynchronizationContext to create a delegate responsible for adding new values. This has the advantage of hiding both the collection and the threading model from the code creating the object.

void DoBackgroundOperation(ObservableCollection<SomeType> col) {
  var context = SynchronizationContext.Current;
  Action<SomeType> addFunc = (SomeType st) => context.Send(() => col.Add(st), null);
  ThreadStart start = () => BackgroundStart(addFunc);
  var t = new Thread(start);
  t.Start();
}

private static void BackgroundStart(Action<SomeType> addFunc) {
  ...
  SomeType t = GetSomeTypeObject();
  addFunc(t);
}
鹿童谣 2024-08-29 06:57:31

在.Net 4.5中,您可以使用线程安全集合、ConcurrentDictionary、ConcurrentBag等,无论哪个适合您的需求:http://msdn.microsoft.com/en-us/library/dd997305.aspx

另请考虑阅读:http://www.codeproject.com/Articles/208361/Concurrent-Observable-Collection-Dictionary-and-So

In.Net 4.5, you can use the Thread-safe collections, ConcurrentDictionary, ConcurrentBag etc, whichever suits your needs : http://msdn.microsoft.com/en-us/library/dd997305.aspx

Please consider reading also : http://www.codeproject.com/Articles/208361/Concurrent-Observable-Collection-Dictionary-and-So

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