线程安全方法调用不起作用

时间:2010-01-02 22:45:56

标签: .net vb.net multithreading invoke

Sup Guys,

我在我的frmMain类上有一个函数,它会在调用后将我的控件更新为其他东西。当我在立即窗口上键入“?Label1.Text”时,文本属性IS更新,但当我去检查表单时,没有任何反应。代码就像这样

Public Sub UpdateUI()
    If (Me.InvokeRequired = True) Then
        Invoke(New MethodInvoker(AddressOf UpdateUI))
    End If
    Label1.Text = "ITS NOT WORKING =\"
End Sub

在我的bgWorker类上:

Private threadUpd As New Threading.Thread(AddressOf Updater)
Private _active as Boolean
Public Sub New()
    _active = True
    threadLimpar.IsBackground = True
    threadLimpar.Start()
End Sub

Public Sub Updater()
    Do
        If (_active = False) Then
            Try
                Thread.Sleep(Timeout.Infinite)
            Catch ex As ThreadInterruptedException
            End Try
        Else
            if(condition...) then
              frmMain.UpdateUI
        End if
    Loop
End Sub

3 个答案:

答案 0 :(得分:3)

这是VB.NET中的一个经典陷阱,每个人在开始使用线程时至少会陷入其中一次:

frmMain.UpdateUI

现在我们无法看到“frmMain”究竟是什么意思。但是您发布此问题的事实表明frmMain是您的主要表单类的名称。不是类中存储对主窗体的引用的字段的名称。

这不起作用。 VB.NET编译器生成的变量允许您作为类引用,就好像它是一个变量具有<ThreadStatic>语义。换句话说,每个线程都将创建自己的表单实例。您可以按照以下方式对其进行排序:

frmMain.UpdateUI
frmMain.Show

但是你会看到窗口的“幽灵”,否则它就像死角一样死了,因为它创建的线程并没有引发消息循环。

您需要对表单进行真正的引用。如果Updater是表单类的方法,那可能是“我”。如果不是,Application.OpenForms可以提供它。最好的办法是通过构造函数为包含Updater的类提供对表单的引用。

答案 1 :(得分:2)

如果InvokeRequired返回true,您可能应该终止该函数,但无论如何都要设置标签文本。以下是您可能会做的事情:

Public Sub UpdateUI()
    If (Me.InvokeRequired = True) Then
        Invoke(New MethodInvoker(AddressOf UpdateUI))
    Else
        Label1.Text = "ITS NOT WORKING =\"
    End If
End Sub

答案 2 :(得分:1)

我想你想要以下内容:

Public Sub UpdateUI()
    If (Me.InvokeRequired) Then
        BeginInvoke(New MethodInvoker(AddressOf UpdateUI))
    Else
        Label1.Text = "ITS NOT WORKING =\"
    End If
End Sub