1

我正在尝试使用Task.Factory.StartNew()来运行后台操作。部分后台操作会更新 ObservableCollection 中保存的对象。我正在使用从 ObservableCollection 派生的自定义类OnCollectionChanged()在集合中某个对象的属性发生更改时触发(请参阅https://stackoverflow.com/a/5256827/62072)。如果有CollectionView绑定到 ObservableCollection 那么我得到一个异常:

System.NotSupportedException:这种类型的 CollectionView 不支持从不同于 Dispatcher 线程的线程更改其 SourceCollection。

我试图避免这个异常,所以我添加了一些代码,只有OnCollectionChanged()在 UI 线程上运行时才会触发。但不知何故我仍然得到例外..

这是我的ItemPropertyChanged()方法:

void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    var a = new NotifyCollectionChangedEventArgs(
        NotifyCollectionChangedAction.Reset);

    if (Thread.CurrentThread.ManagedThreadId
         == Dispatcher.CurrentDispatcher.Thread.ManagedThreadId)
    {
        OnCollectionChanged(a);
    }
}

这是完整的例外:

System.AggregateException was unhandled
  Message=A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread.
  Source=mscorlib
  StackTrace:
       at System.Threading.Tasks.TaskExceptionHolder.Finalize()
       Message=This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread.
      InnerException: System.NotSupportedException
           Source=PresentationFramework
           StackTrace:
                at System.Windows.Data.CollectionView.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)
                at System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e)
                at System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
                at SourceLog.Model.TrulyObservableCollection`1.ItemPropertyChanged(Object sender, PropertyChangedEventArgs e) in C:\github.com\tomhunter-gh\SourceLog\SourceLog.Model\TrulyObservableCollection.cs:line 41
                at System.ComponentModel.PropertyChangedEventHandler.Invoke(Object sender, PropertyChangedEventArgs e)
                at SourceLog.Model.LogEntry.OnPropertyChanged(String property) in C:\github.com\tomhunter-gh\SourceLog\SourceLog.Model\LogEntry.cs:line 44
                at SourceLog.Model.LogEntry.set_Read(Boolean value) in C:\github.com\tomhunter-gh\SourceLog\SourceLog.Model\LogEntry.cs:line 28
                at SourceLog.Model.LogEntry.<MarkAsReadAndSave>b__0() in C:\github.com\tomhunter-gh\SourceLog\SourceLog.Model\LogEntry.cs:line 53
                at System.Threading.Tasks.Task.InnerInvoke()
                at System.Threading.Tasks.Task.Execute()
           InnerException: 

当我明确检查我是时,异常为什么会抱怨我不在 Dispatcher 线程上?

4

2 回答 2

6

Dispatcher.CurrentDispatcher与 UI 线程无关,因为该属性的名称表明它为您提供了当前线程的调度程序。因此,您创建了一个始终返回 true 的检查。使用Application.Current.Dispatcher, 而不是忽略更改,您可以在所述调度程序上调用它。

于 2012-08-24T13:56:35.090 回答
2

当您访问可观察集合时,您需要将上下文切换回 UI 线程。尝试

Action del = () => {YourCodeHere()};
Dispatcher.Invoke(del);
于 2012-08-24T13:53:17.140 回答