You have 2 issues in play. The first is that Main
is a class name, not a runtime reference or object variable. See Idle_Mind's answer for using Me
to get the runtime object reference.
The second problem is that since Class2
is created in DoWork
, it is created on the background thread, which will prevent it from accessing UI controls (which are created on the UI thread). You will get an illegal cross thread operation exception (even if you dont see it).
I'd suggest that Class2
does nothing useful which can't be done using the ReportProgress
method. Getting rid of it also gets rid of the form reference issue since an event is raised on the same thread as the UI controls:
Private WithEvents bgw As BackgroundWorker
...
' in a button click or whatever starts the worker:
bgw = New BackgroundWorker
bgw.WorkerReportsProgress = True
bgw.RunWorkerAsync(5) ' times to loop
...
Private Sub bgw_DoWork(sender As Object,
e As DoWorkEventArgs) Handles bgw.DoWork
' NOTE
' This code executes on a different thread
' so do not reference UI controls!
' e.Argument is the value passed - amount of work
Dim max As Integer = CInt(e.Argument)
For n As Integer = 1 To max
Threading.Thread.Sleep(250) ' emulates work
' causes the ProgressChanged event to fire:
bgw.ReportProgress(n, String.Format("{0} of {1}", n.ToString, max.ToString))
Next
End Sub
Private Sub bgw_ProgressChanged(sender As Object,
e As ProgressChangedEventArgs) Handles bgw.ProgressChanged
'ProgressChanged fires on the UI thread, so it is safe to
' referenece controls here
TextBox4.Text = e.UserState.ToString
TextBox4.Refresh()
End Sub
Paste the code and you can see the message change in the TextBox
. The same would work using your ProgressBar
and ProgressLabel
.
bgw.ReportProgress(n, arg)
The first argument will map to e.ProgressPercentage
in the ProgressChanged
event. The second is optional - UserState
. I used it to pass a string for illustrative purposes (the form can already know the amount of work since it told the BGW what to do.)
If Class2
has some other purpose, you can use it as long as it is created on the UI thread (in the form) and used on that thread (ie in ProgressChanged
event). You also need a method to talk to the controls so you dont have to create a new one each time:
Private myObj As Class2 ' declaration
...
myObj = New Class2(Me) ' instance with frm ref
In class2:
Public Sub Update(value As Integer, msg As String)
frmMain.Progressbar.Value = value
frmMain.ProgressLabel.Text = msg
End Sub
Then in the ProgressChanged
event:
myObj.Update(x, y)
Where x
and y
are the value and message from whereever.