Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
DispatcherObject在WPF中引发了问题和异步/可观察收集问题_Wpf_Multithreading_Events_Asynchronous_Observablecollection - Fatal编程技术网

DispatcherObject在WPF中引发了问题和异步/可观察收集问题

DispatcherObject在WPF中引发了问题和异步/可观察收集问题,wpf,multithreading,events,asynchronous,observablecollection,Wpf,Multithreading,Events,Asynchronous,Observablecollection,下面的代码从Access 2010数据库中提取一组记录;因此,滚动我自己的连接器位。我已经成功地完成了observablecollection,并将它与来自我自己对象的漂亮拖放数据源绑定在一起。然而,像一个愚蠢的人一样,我想异步地做这件事。然而,我有一个小怪物问题,我不知道该怎么解决它!有人能给我提个建议吗?我已经读了很多书,但是在一个周五的下午,这些概念一下子有点太多了,我正在努力取得任何真正的进展 我遇到的问题是: Dim dispatcherObject As dispatcherObje

下面的代码从Access 2010数据库中提取一组记录;因此,滚动我自己的连接器位。我已经成功地完成了observablecollection,并将它与来自我自己对象的漂亮拖放数据源绑定在一起。然而,像一个愚蠢的人一样,我想异步地做这件事。然而,我有一个小怪物问题,我不知道该怎么解决它!有人能给我提个建议吗?我已经读了很多书,但是在一个周五的下午,这些概念一下子有点太多了,我正在努力取得任何真正的进展

我遇到的问题是:
Dim dispatcherObject As dispatcherObject=CType(handler.Target,dispatcherObject)

例外情况是:
无法将类型为“\u Closure$\u 2[SomeRecord\u Viewer.SomeRecord]”的对象强制转换为类型为“System.Windows.Threading.DispatcherObject”。

我已经通过下面的代码创建了一个WPF列表框,但是只是注释掉了ObservableCollectionEx类的一部分。这会导致同步问题,并在输入几百条记录后崩溃

类,该类构建实体的线程列表-在本例中为(SomeRecord的)ObservableCollectionEx:

SomeRecord类的部分代码:

Class SomeRecord
Implements INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler Implements                   INotifyPropertyChanged.PropertyChanged
Private Sub NotifyPropertyChanged( ByVal info As String)
    RaiseEvent PropertyChanged(Me , New PropertyChangedEventArgs (info))
End Sub

...'lots of simple properties.
End Class
线程集合类代码-从另一个在线源代码翻译而来

“我使用PostSharp来尝试捕捉东西。 ` 公共类ObservableCollectionEx(Of T) 继承(T的)可观察集合 '重写事件,以便此类可以访问它 公共阴影事件集合更改为System.Collections.Specialized.NotifyCollectionChangedEventHandler

Protected Overrides Sub OnCollectionChanged( ByVal e As System.Collections.Specialized.NotifyCollectionChangedEventArgs )

    Using BlockReentrancy()

        Dim eventHandler As System.Collections.Specialized.NotifyCollectionChangedEventHandler = Sub () RaiseEvent CollectionChanged(Me , e)
        If (eventHandler Is Nothing) Then Return

        Dim delegates() As [Delegate] = eventHandler.GetInvocationList
*******If I comment this out I can populate the Listbox via a CollectionView, however it dies with issues to do with the list not staying synchronised :).
        'Walk thru invocation list 
        For Each handler As System.Collections.Specialized.NotifyCollectionChangedEventHandler     In delegates
            Dim dispatcherObject As DispatcherObject = CType (handler.Target, DispatcherObject)
            ' If the subscriber is a DispatcherObject and different thread
            If (( Not (dispatcherObject) Is Nothing) AndAlso (dispatcherObject.CheckAccess = False )) Then
                ' Invoke handler in the target dispatcher's thread
                dispatcherObject.Dispatcher.Invoke(DispatcherPriority .DataBind, handler, Me, e)
            Else
                handler( Me, e)
            End If
        Next

*******End of stuff I comment out to get working partially***

    End Using
End Sub
End Class

从我看来,你有两个问题

  • 您正在将局部变量
    eventHandler
    分配给匿名方法,而不是实际的事件处理程序。应该是:

    Dim eventHandler As NotifyCollectionChangedEventHandler = CollectionChangedEvent
    
    注意:您需要在VB中使用
    CollectionChangedEvent
    ,而不是
    CollectionChanged

  • 您正在使用
    CType
    将目标强制转换为
    DispatcherObject
    ,如果目标不是
    DispatcherObject
    ,则此操作无效。改用
    TryCast

    Dim dispatcherObject As DispatcherObject = TryCast(handler.Target, DispatcherObject)
    
  • 您还可以使用
    IsNot
    ,在下一行整理测试:

    If dispatcherObject IsNot Nothing AndAlso Not dispatcherObject.CheckAccess Then
    

    警告-下面的代码与C#版本的行为不同。关键的区别似乎是在VB中你不能重写事件(到底为什么不能?),而在C中你可以

    结果是处理程序在VB中为Nothing,但在C中为Nothing:(

    因此语法构建没有错误,但是VB版本从来没有做过任何事情

    用VB重做更新后的答案。谢谢

    注意,我还不能用实体框架来实现这一点,但我认为这是一个me和EF问题,而不是集合问题

    代码本身是为任何感兴趣的人准备的。我的列表现在填充得非常好。但是,在我更新之前,我会对我的答案稍加保留,比如说我是如何进行广泛测试的:)

    然而,预兆是好的——这里是原C#作者的网站:


    End Class

    Hi@Richard thank-我不得不使用匿名方法,因为我无法理解这个错误:
    error 1的公共阴影事件CollectionChanged(发送者作为对象,e作为System.Collections.Specialized.NotifyCollectionChangedEventArgs)是一个事件,不能直接调用。使用“RaiseEvent”语句引发事件这段代码来自C#翻译,其中的作业做得非常好,但由于某些原因,它在VB中不起作用;语法上的差异意味着翻译失败了——我将尝试获取原始C#版本,然后将其放入DLL中——我本来应该这样做的。@Richard:根据,你需要在VB中使用
    CollectionChangedEvent
    。我将更新我的答案。我已标记为答案,谢谢;因为随着这些变化,集合本身在VB中工作,这是我在你的NB之前无法做到的。非常感谢!现在强迫EF使用它。还有一个问题:)。不幸的是,我从来没有尝试过触发CollectionChanged-我认为VB不允许事件重写,这与C#不同:(
    If dispatcherObject IsNot Nothing AndAlso Not dispatcherObject.CheckAccess Then
    
    Public Class ObservableCollectionEx(Of T)
    Inherits ObservableCollection(Of T)
    
    
    
    'Override the event so this class can access it
    Public Shadows Event CollectionChanged As NotifyCollectionChangedEventHandler
    
    Protected Overrides Sub OnCollectionChanged(ByVal e As NotifyCollectionChangedEventArgs)
        Using BlockReentrancy()
            Dim eventHandler As System.Collections.Specialized.NotifyCollectionChangedEventHandler = CollectionChangedEvent
            If eventHandler Is Nothing Then
                Return
            End If
    
    
            Dim delegates() As [Delegate] = CollectionChangedEvent.GetInvocationList
            'Walk thru invocation list
            For Each handler As NotifyCollectionChangedEventHandler In delegates
                Dim dispatcherObject As DispatcherObject = TryCast(handler.Target, DispatcherObject)
                ' If the subscriber is a DispatcherObject and different thread
                If dispatcherObject IsNot Nothing AndAlso Not dispatcherObject.CheckAccess Then
                    ' Invoke handler in the target dispatcher's thread
                    dispatcherObject.Dispatcher.Invoke(DispatcherPriority.DataBind, handler, Me, e)
                Else
                    handler(Me, e)
                End If
            Next
        End Using
    End Sub