【问题标题】:Invalid cross-thread exception in silverlightSilverlight 中的无效跨线程异常
【发布时间】:2012-09-08 05:54:43
【问题描述】:

我有一个 VB silverlight 应用程序,它将成为一款纸牌游戏。我一直在尝试让单个卡片(我以编程方式创建,作为 Silverlight“图像”控件,包装在他们自己的“CardImage”类中)在鼠标悬停时移动。我希望它们在鼠标悬停时有点“弹出”,然后在鼠标离开时回落。

基本上,我在 mouseenter 上移动 Image.Margin.Top 5 个像素,在 mouseleave 事件上向下 5 个像素。

我一直在经历关于无效跨线程访问的可怕“未处理异常”,并且在完成我的作业后,我了解了 UI 线程与工作线程等,并试图将整个“begininvoke”实践以变得更加线程安全。

问题出在:异常仍在发生。

这是我的代码:

Public Class CardImage

Public Disp As Dispatcher = Deployment.Current.Dispatcher
Public WithEvents Image As New Image

Private Sub MouseEnter(ByVal sender As Object, ByVal e As MouseEventArgs) Handles Image.MouseEnter
    Try
        Invoke(Sub() Image.Margin = New Thickness(Image.Margin.Left, Image.Margin.Top - 5, 0, 0))
    Catch ex As Exception

    End Try
End Sub
Private Sub MouseLeave(ByVal sender As Object, ByVal e As MouseEventArgs) Handles Image.MouseLeave
    Try
        Invoke(Sub() Image.Margin = New Thickness(Image.Margin.Left, Image.Margin.Top + 5, 0, 0))
    Catch ex As Exception

    End Try
End Sub

Private Sub Invoke(ByVal act As Action)
    If Disp.CheckAccess Then
        act.Invoke()
    Else
        Disp.BeginInvoke(act)
    End If
End Sub
End Class

当我在所有显示的卡片上快速移动鼠标时引发异常(作为 13 张卡片的“手”)。请记住,玩家最终可能会做这种事情......我真的不希望应用程序崩溃,因为一些患有 ADHD 的用户决定他们希望卡片一遍又一遍地涟漪和“做波浪”,一边不耐烦地等着别人打牌。

关于为什么我的 UI 线程仍然没有使用更新图像边距的线程的任何提示?

【问题讨论】:

  • 仅供参考:我也尝试过带有递归回调的“image.checkaccess”方法。
  • 好的,我认为我的回答是错误的。由于您的方法来自事件处理程序,我认为它们已经在 UI 线程上,这就是错误仍然发生的原因。您是否以编程方式在另一个线程上创建 CardImage 实例?
  • @Kratz 卡片图像是由于在silverlight 主页面上触发按钮单击事件而创建的。该按钮(它只是一个“处理”新测试手的按钮)创建所有 52 个 CardImage 对象,并排列它们。所以你会认为这一切都在 UI 线程上。
  • 是什么让您认为MouseEnterMouseLeave 在不同的线程上执行?在我看来,它们就像典型的 UI 鼠标事件,这意味着它们已经在 UI 线程上。也许您的问题出在其他地方。
  • 您说它没有触发“catch”代码中的断点,但是您是否尝试过在 App.xaml.cs 的 Application_UnhandledException 事件处理程序中设置断点?如果它被击中,您可以查看 e.ExceptionObject 以获取其堆栈跟踪。

标签: vb.net multithreading silverlight user-interface


【解决方案1】:

“图像”是在创建 CardImage 的线程的上下文中创建的。如果那不是 UI-Thread 而是工作线程,则您无法从 UI-Thread 访问它(到您调度鼠标事件的位置。

在 UI 线程中创建它:

Public WithEvents Image As Image

Public Sub New()

   Image = Invoke(Function()
                       return New Image
                  End Function)

End Sub

Private Function Invoke(ByVal procedure As Func(of System.Windows.Controls))

    If Disp.CheckAccess Then
       return procedure.Invoke()
    Else
        return Disp.Invoke(procedure)
    End If

End Function 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多