Unexpected\false positive error: 'Invoke or BeginInvoke cannot be called on a control until the window handle has been created'
Unexpected\false positive error: 'Invoke or BeginInvoke cannot be called on a control until the window handle has been created'
在特定的异步情况下,我收到一个 System.Reflection.TargetInvocationException
异常并显示此错误消息:
Invoke or BeginInvoke cannot be called on a control until the window
handle has been created
请注意这不是一个重复的问题,我将在下面解释原因。我知道错误的含义,但不能 be/should 不抛出异常,因为 window 的句柄是在我的代码中创建的。
我开始认为我收到的这个错误消息可能是 .NET Framework 中的一个新错误,我需要有人的帮助来澄清这是否是我在代码中的错还是我的错,以及如何解决这个问题。
我只有这个 class 代表主要申请表:
Public NotInheritable Class Main : Inherits Form
Private Async Sub ButtonMirror_Click(sender As Object, e As EventArgs) Handles ButtonMirror.Click
' Synchronous.
' Dim sucess As Boolean = MirrorUtil.BuildMirror
' Asynchronous.
Dim t As Task(Of Boolean) = Task.Run(Of Boolean)(AddressOf MirrorUtil.BuildMirror)
Dim sucess As Boolean = Await t
End Sub
End Class
请注意,事件处理程序指定了 Async
关键字。
这是BuildMirror
方法
Friend NotInheritable Class MirrorUtil
Friend Shared Function BuildMirror() As Boolean
My.Forms.Main.Invoke(Sub() My.Forms.Main.Visible = False)
End Function
End Class
问题出在 BuildMirror
方法的块内,只有当我像上面的代码那样异步调用它时才会发生,Main.Invoke()
方法抛出提到的异常,如果我执行对 Main.IsHandleCreated
的调用,令人惊讶的是 returns False
! ...只有当我异步调用 BuildMirror
方法时,我才坚持。
我想了解发生了什么,以及如何解决它。当然,主应用程序表单是实例化的并且是可见的,window 句柄已创建,那么它不应该抛出该异常...
我在尝试调试真正的问题时发现了这个奇怪的问题,这不是我在这个问题中暴露的问题,但是我认为这个奇怪的问题是我真正的问题的原因,所以我很感激一个解决方案为此。
我会简化这个。你不需要另一个 class.
Public NotInheritable Class Main : Inherits Form
Private Async Sub ButtonMirror_Click(sender As Object, e As EventArgs) Handles ButtonMirror.Click
Me.Invoke(Sub() Me.Visible = False)
End Sub
End Class
考虑有关问题的这些事实:
当你在另一个线程中调用My.Forms.Main
时,你得到的表单不是你在主线程中创建和显示的表单。这是 Main
的新实例。但是如果你在主线程中调用它,它就是创建其句柄的现有实例。 (My.Forms.Something
将return 主窗体的现有实例,对于其他窗体,创建一个新实例并缓存它并使用它。)
调用Invoke
方法会抛出异常,如果窗体句柄没有创建,窗体句柄会在你展示后创建。
当你在另一个线程中调用My.Forms.Main.Invoke(Sub() My.Forms.Main.Visible = False)
时,My.Forms.Main
将是一个新的实例,并且它的句柄没有被创建,所以调用Invoke
会导致你的异常收到。
在特定的异步情况下,我收到一个 System.Reflection.TargetInvocationException
异常并显示此错误消息:
Invoke or BeginInvoke cannot be called on a control until the window handle has been created
请注意这不是一个重复的问题,我将在下面解释原因。我知道错误的含义,但不能 be/should 不抛出异常,因为 window 的句柄是在我的代码中创建的。
我开始认为我收到的这个错误消息可能是 .NET Framework 中的一个新错误,我需要有人的帮助来澄清这是否是我在代码中的错还是我的错,以及如何解决这个问题。
我只有这个 class 代表主要申请表:
Public NotInheritable Class Main : Inherits Form
Private Async Sub ButtonMirror_Click(sender As Object, e As EventArgs) Handles ButtonMirror.Click
' Synchronous.
' Dim sucess As Boolean = MirrorUtil.BuildMirror
' Asynchronous.
Dim t As Task(Of Boolean) = Task.Run(Of Boolean)(AddressOf MirrorUtil.BuildMirror)
Dim sucess As Boolean = Await t
End Sub
End Class
请注意,事件处理程序指定了 Async
关键字。
这是BuildMirror
方法
Friend NotInheritable Class MirrorUtil
Friend Shared Function BuildMirror() As Boolean
My.Forms.Main.Invoke(Sub() My.Forms.Main.Visible = False)
End Function
End Class
问题出在 BuildMirror
方法的块内,只有当我像上面的代码那样异步调用它时才会发生,Main.Invoke()
方法抛出提到的异常,如果我执行对 Main.IsHandleCreated
的调用,令人惊讶的是 returns False
! ...只有当我异步调用 BuildMirror
方法时,我才坚持。
我想了解发生了什么,以及如何解决它。当然,主应用程序表单是实例化的并且是可见的,window 句柄已创建,那么它不应该抛出该异常...
我在尝试调试真正的问题时发现了这个奇怪的问题,这不是我在这个问题中暴露的问题,但是我认为这个奇怪的问题是我真正的问题的原因,所以我很感激一个解决方案为此。
我会简化这个。你不需要另一个 class.
Public NotInheritable Class Main : Inherits Form
Private Async Sub ButtonMirror_Click(sender As Object, e As EventArgs) Handles ButtonMirror.Click
Me.Invoke(Sub() Me.Visible = False)
End Sub
End Class
考虑有关问题的这些事实:
当你在另一个线程中调用
My.Forms.Main
时,你得到的表单不是你在主线程中创建和显示的表单。这是Main
的新实例。但是如果你在主线程中调用它,它就是创建其句柄的现有实例。 (My.Forms.Something
将return 主窗体的现有实例,对于其他窗体,创建一个新实例并缓存它并使用它。)调用
Invoke
方法会抛出异常,如果窗体句柄没有创建,窗体句柄会在你展示后创建。
当你在另一个线程中调用My.Forms.Main.Invoke(Sub() My.Forms.Main.Visible = False)
时,My.Forms.Main
将是一个新的实例,并且它的句柄没有被创建,所以调用Invoke
会导致你的异常收到。