I am stuck updating a progressbar from a different thread. I did get it running in the simplest way, but then cleaning the code gets me stuck.
My testing code looks like all the examples on the web related to backgroundworker and BeginInvoke.
FormP is the Progressbar-Form. This works:
Public Class Form1
Private Delegate Sub delegate_ProgressUpdate(ByVal paramValue As Integer,
ByVal paramMax As Integer)
Private Sub Button1_Click(sender As System.Object,
e As System.EventArgs) Handles Button1.Click
' Test 01:
' Show Progressbar via BGW
' All functions are within Form1
Dim bgw As New BackgroundWorker()
AddHandler bgw.DoWork, AddressOf BGW_Sample01_DoWork
FormP.Show(Me)
bgw.RunWorkerAsync()
End Sub
Private Sub invokeMe_ProgressUpdate(ByVal paramValue As Integer, ByVal paramMax As Integer)
FormP.ProgressBar1.Maximum = paramMax
FormP.ProgressBar1.Value = paramValue
FormP.ProgressBar1.Update()
End Sub
Private Sub BGW_Sample01_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs)
For i As Integer = 1 To 10
Threading.Thread.Sleep(500) ' Test delay
Me.BeginInvoke(New delegate_ProgressUpdate(AddressOf invokeMe_ProgressUpdate),
i, 10)
Next
MessageBox.Show("Fertig")
End Sub
If I try to make things work more orderly encapsulated in FormP, it doesn't work.
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
Dim bgw As New BackgroundWorker
AddHandler bgw.DoWork, AddressOf BGW_Sample02_DoWork
FormP.Show(Me)
bgw.RunWorkerAsync()
End Sub
Private Sub BGW_Sample02_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs)
For i As Integer = 1 To 10
Threading.Thread.Sleep(500)
FormP.SetProgress(i, 10)
Next
MessageBox.Show("Fertig")
End Sub
' ########## FormP #################
Public Class FormP
Private Delegate Sub delegate_ProgressUpdate(ByVal value As Integer, ByVal maximum As Integer)
Public Sub SetProgress(ByVal paramValue As Integer, ByVal paramMaximum As Integer)
If Me.InvokeRequired Then
Me.Invoke(New delegate_ProgressUpdate(AddressOf Me.SetProgress), paramValue, paramMaximum)
Else
Me.ProgressBar1.Maximum = paramMaximum
Me.ProgressBar1.Value = paramValue
Me.ProgressBar1.Update()
End If
End Sub
End Class
FormP does not freeze, but UI is not updated. Actually Me.InvokeRequired is false and I think that's where I begin to miss some important parts. I tried Form1.InvokeRequired here, but it's false as well. My understanding is: the calling thread here is the bgw thread, no matter in what class the code is that this thread calls... That seems not to be it?
Thanks for any thoughts.
What worked eventually:
Private frmP As FormP
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
Dim bgw As New BackgroundWorker
If Me.frmP IsNot Nothing AndAlso Me.frmP.Visible Then Return
Me.frmP = New FormP
Me.frmP.Show(Me)
AddHandler bgw.DoWork, AddressOf BGW_Sample02_DoWork
bgw.RunWorkerAsync(New Object() {Me.frmP})
End Sub
Private Sub BGW_Sample02_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs)
Dim objFrmP As FormP = DirectCast(e.Argument(0), FormP)
For i As Integer = 1 To 10
objFrmP.setProgress(i, 10)
Threading.Thread.Sleep(500)
Next
MessageBox.Show("Finished")
End Sub
The Progress-Dialog-Code in FormP:
Public Sub setProgress(paramValue As Integer, paramMaximum As Integer)
If Me.InvokeRequired Then
' defining a delegate type is not really necessary
Me.Invoke(Sub() Me.setProgress(paramValue, paramMaximum))
Else
Me.ProgressBar1.Maximum = paramMaximum
Me.ProgressBar1.Value = paramValue
Me.ProgressBar1.Update()
End If
End Sub