在创建窗口句柄之前,无法在控件上调用VB.NET Invoke,但是创建了句柄

时间:2014-09-03 12:50:35

标签: vb.net multithreading winforms invoke

这是我的情况,有2个类和我的主要表单Form1:

Class1:有一个方法doSomethingAndCall(callback),它创建一个新线程 Class2:具有动态创建的控件,带有一个触发Class1.doSomethingAndCall(newCallback)的按钮

在代码中看起来像这样(它从Class2.Button_Click开始):

Class Class1
  public shared sub doSomethingAndCallAsync(state as object)
    Console.WriteLine(Form1.InvokeRequired) 'output: false
    Console.WriteLine(Form1.IsHandleCreated) 'output: false
    Form1.Invoke(state.callback) 'throws System.InvalidOperationException
  end sub

  public shared sub doSomethingAndCall(callback as object)
    System.Threading.ThreadPool.QueueUserWorkItem(AddressOf doSomethingAndCallAsync, New With {.callback = callback})
  end sub
End Class

Class Class2
  Public Delegate Sub doSomethingDelegate()

  Public Sub doSomething()
    Console.WriteLine("success!")
  End Sub

  Public Sub Button_Click(ByVal sender As Object, ByVal e As System.EventArgs)
    Class1.doSomethingAndCall(New doSomethingDelegate(AddressOf doSomething))
  End Sub
End Class

我得到的确切例外是:

  

在创建窗口句柄之前,无法在控件上调用Invoke或BeginInvoke

并且我可以看到第4行中的console.WriteLine向我显示该表单实际上并未创建。所以我添加了这个处理程序,现在它真的让人感到困惑:

 Private Sub Form1_HandleCreated(sender As Object, e As System.EventArgs) Handles Me.HandleCreated
        Console.WriteLine("Handle created") 'Output: Handle created, when running program
  End Sub

  Private Sub Form1_HandleDestroyed(sender As Object, e As System.EventArgs) Handles Me.HandleDestroyed
        Console.WriteLine("Handle destroyed") 'Will never Output!
  End Sub

所以它被创造并且永远不会被破坏但是如果我点击按钮它仍然是不可用的? - 任何人都可以向我解释发生了什么,以及如何正确回拨,谢谢!

1 个答案:

答案 0 :(得分:5)

My.Forms.Form1 aka的实例。 Form1在每个帖子中都会有所不同。您需要一个正确实例的句柄。在Form1上放一个按钮,然后添加以下代码:

Public Class Form1

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Threading.Tasks.Task.Factory.StartNew(Sub() Class1.Wrong())
        Threading.Tasks.Task.Factory.StartNew(Sub() Class1.Correct(Me))
    End Sub

End Class

Public Class Class1

    Public Shared Sub Wrong()
        Debug.WriteLine(String.Format("(Other thread, wrong) InvokeRequired={0}, IsHandleCreated={1}", Form1.InvokeRequired, Form1.IsHandleCreated))
    End Sub

    Public Shared Sub Correct(instance As Form1)
        Debug.WriteLine(String.Format("(Other thread, correct) InvokeRequired={0}, IsHandleCreated={1}", instance.InvokeRequired, instance.IsHandleCreated))
    End Sub

End Class

<强>输出

  

(其他线程,正确)InvokeRequired = True,IsHandleCreated = True

  

(其他线程,错误)InvokeRequired = False,IsHandleCreated = False