Изменяемая асинхронно наблюдаемая коллекция ObservableCollection
Наблюдаемые коллекции ObservableCollection в WPF можно изменять толкько в потоке пользовательского интерфейса. Однако можно несколько изменить данную коллекцию таким образом, чтобы можно было это делать из фонового потока. Например, вот так:
Imports System Imports System.Collections.Generic Imports System.Collections.ObjectModel Imports System.Collections.Specialized Imports System.Diagnostics Imports System.Windows.Threading Public Class ObservableCollectionThreadSafe(Of T) Inherits ObservableCollection(Of T) 'наследуем от наблюдаемой коллекции 'Переопределяем событие изменения коллекции Public Shadows Event CollectionChanged As NotifyCollectionChangedEventHandler #Region "КОНСТРУКТОРЫ" Public Sub New() MyBase.New() End Sub Public Sub New(items As IEnumerable(Of T)) MyBase.New(items) End Sub #End Region '/КОНСТРУКТОРЫ Protected Overrides Sub OnCollectionChanged(e As NotifyCollectionChangedEventArgs) Using MyBase.BlockReentrancy() 'используем BlockReentrancy(), который запрещает выполнение повторных попыток изменения коллекции Dim eventHandler As NotifyCollectionChangedEventHandler = Me.CollectionChangedEvent If (eventHandler IsNot Nothing) Then Dim delegates As [Delegate]() = eventHandler.GetInvocationList() For Each handler As NotifyCollectionChangedEventHandler In delegates 'идём по списку вызовов Dim dispatcherObject As DispatcherObject = TryCast(handler.Target, DispatcherObject) If (dispatcherObject IsNot Nothing) AndAlso (Not dispatcherObject.CheckAccess()) Then 'Если подписчик - DispatcherObject И другой поток dispatcherObject.Dispatcher.Invoke(DispatcherPriority.DataBind, handler, Me, New Object() {e}) 'вызываем обработчик в целевом потоке диспетчера Else handler(Me, e) 'иначе запускаем обработчик как есть End If Next End If End Using End Sub End Class