Ce qui suit est une amélioration sur la mise en œuvre trouvés par Jonathan. Tout d'abord, il s'exécute à chaque gestionnaire d'événement sur le répartiteur associés avec elle plutôt que de supposer qu'ils sont tous sur le même (UI) répartiteur. Deuxièmement, il utilise BeginInvoke pour permettre de continuer le traitement pendant que nous attendons pour le répartiteur de devenir disponibles. Cela rend la solution beaucoup plus rapide dans les situations où le thread d'arrière-plan est de faire beaucoup de mises à jour avec traitement entre chacun d'entre eux. Peut-être plus important encore, il permet de surmonter les problèmes causés par le blocage lors de l'attente pour l'Invoquer (blocages peuvent se produire par exemple lors de l'utilisation de WCF avec ConcurrencyMode.Unique).
public class MTObservableCollection<T> : ObservableCollection<T>
{
public override event NotifyCollectionChangedEventHandler CollectionChanged;
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
NotifyCollectionChangedEventHandler CollectionChanged = this.CollectionChanged;
if (CollectionChanged != null)
foreach (NotifyCollectionChangedEventHandler nh in CollectionChanged.GetInvocationList())
{
DispatcherObject dispObj = nh.Target as DispatcherObject;
if (dispObj != null)
{
Dispatcher dispatcher = dispObj.Dispatcher;
if (dispatcher != null && !dispatcher.CheckAccess())
{
dispatcher.BeginInvoke(
(Action)(() => nh.Invoke(this,
new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset))),
DispatcherPriority.DataBind);
continue;
}
}
nh.Invoke(this, e);
}
}
}
Parce que nous sommes à l'aide de BeginInvoke, il est possible que le changement ait été notifiée, est annulée avant que le gestionnaire est appelé. Ce serait normalement entraîner un "Index était hors de portée." exception levée lorsque les arguments de l'événement sont vérifiées par rapport à la nouvelle (modifié) l'état de la liste. Afin d'éviter cela, tous les retardée événements sont remplacés par Réinitialiser les événements. Cela pourrait provoquer un excès de redessiner dans certains cas.