【问题标题】:Vb.net Difference between assigning properties directly and using invoke methodvb.net直接分配属性和使用invoke方法的区别
【发布时间】:2019-05-10 06:11:03
【问题描述】:

下面提到的两条线都有效。它用于启用或禁用表单内的按钮。但问题是我们为什么要使用 form.Invoke 方法而不是直接分配方法。

方法一:

frmPrint.Invoke(Sub() frmPrint.btnCancel.Enabled = False)

方法二:

frmPrint.btnCancel.Enabled = False

谢谢, 萨拉提

【问题讨论】:

  • [Control].Invoke(delegate) 当属性/方法从 UI 线程以外的线程设置/调用时。您应该使用.BeginInvoke() 而不是Invoke()
  • 一般来说,我不能告诉你为什么你应该使用 Invoke(...) 而不是直接给控件属性赋值。但我可以告诉你,什么时候有意义这样做:正如 Jimi 已经提到的,所有 UI 元素都是由 UI 线程专门驱动的,如果到目前为止我可以这么称呼它的话。如果您现在想从另一个线程调用 frm.btnCancel.Enabled = False,这将失败,除非您使用 Invoke(...) 执行此操作。因此,如果您的代码(可能)未在 UI 线程中运行,您应该使用这种方式。甚至还有其他技术可以确保代码由 UI 线程执行。
  • 感谢@jimi 和 user1470240,现在我对这种方法有了一些想法。

标签: .net vb.net winforms


【解决方案1】:

Invoke() 方法在拥有控件底层窗口句柄的线程上执行指定的委托。

简而言之,当从不是 GUI 主线程的其他线程更新 GUI 时,应使用 Invoke() 方法。

因此,如果您从主线程更新 GUI,则不必使用 Invoke() 方法。

安全的多线程 GUI 更新

当从其他线程更新 GUI 时,你不能这样做,因为Cross-thread exception 将被抛出:

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim t As New Threading.Thread(AddressOf changeGUI)
    t.Start()
End Sub


Private Sub changeGUI()
    Button2.Enabled = False
End Sub

但是当使用Invoke() 时,GUI 将在委托的帮助下安全更新,所以你应该这样做:

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim t As New Threading.Thread(AddressOf changeGUIThreadSafe)
    t.Start()
End Sub


Private Sub changeGUIThreadSafe()
    Me.Invoke(Sub() Button2.Enabled = False)
End Sub

【讨论】:

  • 请原谅标记为答案的延迟。谢谢乔娜。
猜你喜欢
  • 1970-01-01
  • 2018-07-09
  • 2012-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-13
  • 2011-02-02
相关资源
最近更新 更多