Multithreading for a progressbar and code locations (vb.net)?

10,449

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
Share:
10,449
KekuSemau
Author by

KekuSemau

Updated on June 05, 2022

Comments

  • KekuSemau
    KekuSemau almost 2 years

    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.