开发者

Thread Safe Method Invoke doesnt work

开发者 https://www.devze.com 2022-12-15 02:38 出处:网络
Sup Guys, I Have a Function on my frmMain Class wich will update my control to something else after an invoke. When i type \"?Label1.Text\" on the Immediate Window, the text property IS updated, but

Sup Guys,

I Have a Function on my frmMain Class wich will update my control to something else after an invoke. When i type "?Label1.Text" on the Immediate Window, the text property IS updated, but when i go check the Form, nothing happened. The code is just like this

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

On my bgWorker Class:

Private threadUpd As New Threading.Thread(AddressOf Upd开发者_JS百科ater)
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


It is a classic trap in VB.NET, everyone falls into it at least once when they start using threads:

frmMain.UpdateUI

Now we can't see what exactly "frmMain" means. But the fact that you posted this question suggests that frmMain is the name of your main form class. Not the name of a field in your class that stores a reference to the main form.

That doesn't work. The variable that the VB.NET compiler generates to allow you to reference as class as though it is a variable has <ThreadStatic> semantics. In other words, every thread will create its own instance of a the form. You can sorta see it when you write it like this:

frmMain.UpdateUI
frmMain.Show

But you'll see a "ghost" of the window, it is otherwise dead as a doornail since the thread it was created on is not pumping a message loop.

You'll need a real reference to the form. That could be "Me" if Updater is a method of the form class. If it isn't, Application.OpenForms could provide it. Best thing to do is the give the class that contains Updater a reference to the form through its constructor.


You probably should terminate the function if InvokeRequired returns true, but you're setting the label text anyway. Here's what you might do:

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


I think you want the following:

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

精彩评论

暂无评论...
验证码 换一张
取 消