Actualizar un ObservableCollection en un hilo separado

En una aplicación de WPF, las consultas de LINQ a SQL rellenan y actualizan ObservableCollection. Luego, los objetos de UI se actualizan utilizando los valores de este ObservableCollection.

¿Es posible y razonable que las operaciones de actualización de este ObservableCollection de LINQ a SQL se hayan ejecutado en un hilo separado?

En caso afirmativo, será, en este caso, una y la misma instancia de este ObservableCollection? (Quiero decir, si no es el mismo para tomar valores del contexto de datos LINQ y el de dar valores para actualizar la IU, entonces no podré actualizar la IU)

Con la clase incorporada ObservableCollection , no puede cambiar el contenido de un hilo separado si la interfaz de usuario está vinculada a la colección, arroja una NotSupportedException (pero la notificación de cambio para las propiedades de los elementos de colección funciona bien). Escribí una AsyncObservableCollection para manejar este caso. Funciona al invocar a los controladores de eventos en el contexto de sincronización de la interfaz de usuario

.Net 4.5 proporciona una solución dentro de la clase BindingOperations.

Ahora puede usar el método BindingOperations.EnableCollectionSynchronization de la siguiente manera:

 private readonly object _personCollectionLock; private ObservableCollection _personCollection; public ObservableCollection PersonCollection { get { return _personCollection; } set { _personCollection = value; BindingOperations.EnableCollectionSynchronization(_personCollection, _personCollectionLock); } 

Acabo de probar esto en mi entorno de desarrollo, pero parece que todo funciona correctamente ahora cuando actualizo la colección desde un hilo de fondo.

Hay una discusión más profunda de esta solución en: http://10rem.net/blog/2012/01/16/wpf-45-observable-collection-cross-thread-change-notification

La entrada de MSDN para este método está en: https://msdn.microsoft.com/en-us/library/system.windows.data.bindingoperations.enablecollectionsynchronization(v=vs.110).aspx

En nuestra aplicación, tenemos un TreeView vinculado a un ObservableCollection, que actualizamos regularmente en un hilo de fondo, solicitando datos de nuestro almacenamiento. ¡Funciona perfectamente!

Whoops. Fui mal informado =))

Correcto, en realidad estamos subclasificando la ObservableCollection y reemplazamos el método OnCollectionChanged para evitar la excepción de la interferencia cruzada de la interfaz de usuario. Estamos usando esta solución :

 public class MTObservableCollection : ObservableCollection { public override event NotifyCollectionChangedEventHandler CollectionChanged; protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) { var eh = CollectionChanged; if (eh != null) { Dispatcher dispatcher = (from NotifyCollectionChangedEventHandler nh in eh.GetInvocationList() let dpo = nh.Target as DispatcherObject where dpo != null select dpo.Dispatcher).FirstOrDefault(); if (dispatcher != null && dispatcher.CheckAccess() == false) { dispatcher.Invoke(DispatcherPriority.DataBind, (Action)(() => OnCollectionChanged(e))); } else { foreach (NotifyCollectionChangedEventHandler nh in eh.GetInvocationList()) nh.Invoke(this, e); } } } } 

Sin esa anulación obtendrías una excepción como esa

System.NotSupportedException: este tipo de CollectionView no admite cambios en su SourceCollection a partir de un hilo diferente del hilo Dispatcher.

Ahora el único problema que tenemos es la posición del elemento seleccionado, en algunos casos, si el elemento seleccionado actualmente se elimina de la colección, TreeView mueve la selección al siguiente elemento (lo que causa algunas otras acciones de IU innecesarias en nuestra aplicación). Pero ese es un pequeño problema.

Intentando entender tu pregunta aquí:

 escenario 1
 1. LINQ to SQL recupera el conjunto de datos de la base de datos y lo agrega a ObservableCollection A.
 2. Periódicamente, se recuperan más datos de la base de datos y se agregan a A. Los datos antiguos se eliminan de A.

 Escenario 2
 1. LINQ to SQL recupera el conjunto de datos de la base de datos y lo agrega a ObservableCollection A.
 2. Periódicamente, los datos en A se actualizan con nuevos datos de la base de datos (sin agregar / eliminar).

Con el Escenario 1, vas a tener que usar el hilo de UI. El hilo de UI posee el ObservableCollection y obtendrá una excepción si intenta usarlo en otro hilo.

Con el Escenario 2, pulgares arriba. Siempre que no intente agregar o quitar elementos de la colección en sí, puede actualizar el elemento tanto como desee en una cadena de fondo.