1

Task.Factory.StartNew()バックグラウンド操作を実行するために使用しようとしています。バックグラウンド操作の一部は、ObservableCollection に保持されているオブジェクトを更新します。ObservableCollection から派生したカスタム クラスを使用してOnCollectionChanged()、コレクション内のオブジェクトの 1 つのプロパティが変更されたときに起動します ( https://stackoverflow.com/a/5256827/62072を参照)。CollectionViewObservableCollection へのバインドがある場合、例外が発生します。

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 スレッドにいることを明示的に確認したときに、私が 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 に答える