Search code examples
vb.netbackgroundworker

Update label from mainform class with backgroundworker from another class


I have two classes.

Public Class MainForm

     Private Project As clsProject


Private Sub btnDo_Click
   ...
   Backgroundworker.RunWorkerAsync()

End Sub
 Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork


    Project = New clsProject


End Sub

and two methods inside MainForm

 Public Shared Sub setLabelTxt(ByVal text As String, ByVal lbl As Label)
    If lbl.InvokeRequired Then
        lbl.Invoke(New setLabelTxtInvoker(AddressOf setLabelTxt), text, lbl)
    Else
        lbl.Text = text
    End If
End Sub
Public Delegate Sub setLabelTxtInvoker(ByVal text As String, ByVal lbl As Label)
end class

I want to update the labels of MainForm from the clsProject constructor.

 MainForm.setLabelTxt("Getting prsadasdasdasdasdry..", MainForm.lblProgress)

but it does not update them. What am I doing wrong?


Solution

  • You cannot execute any action on GUI-elements from the BackgroundWorker directly. One way to "overcome" that is by forcing the given actions to be performed from the main thread via Me.Invoke; but this is not the ideal proceeding. Additionally, your code mixes up main form and external class (+ shared/non-shared objects) what makes the whole structure not too solid.

    A for-sure working solution is relying on the specific BGW methods for dealing with GUI elements; for example: ProgressChanged Event. Sample code:

    Public Class MainForm
        Private Project As clsProject
        Public Shared bgw As System.ComponentModel.BackgroundWorker
    
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            bgw = BackgroundWorker1 'Required as far as you want to called it from a Shared method
    
            BackgroundWorker1.WorkerReportsProgress = True
            BackgroundWorker1.RunWorkerAsync()
        End Sub
    
        Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
            Project = New clsProject
        End Sub
    
        Public Shared Sub setLabelTxt(ByVal text As String)
            bgw.ReportProgress(0, text) 'You can write any int as first argument as far as will not be used anyway
        End Sub
    
        Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
            Me.Label1.Text = e.UserState 'You can access the given GUI-element directly
            Me.Label1.Update()
        End Sub
    End Class
    
    Public Class clsProject
        Public Sub New()
            MainForm.setLabelTxt("Getting prsadasdasdasdasdry..")
        End Sub
    End Class