Изменяемая асинхронно наблюдаемая коллекция 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
