Background thread doesn't show progress?

littlebigman

Well-known member
Joined
Jan 5, 2010
Messages
75
Programming Experience
Beginner
Hello

I was looking for a solution to run a lengthy job (looking for files on the fixed drives) withouth freezing the UI, and saw that using a BackGroundWorker control is the recommended solution.

Problem is, I don't see its ProgressChange event being triggered:

VB.NET:
Imports System.IO
Imports System.Text.RegularExpressions

Public Class Form1
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Button1.Enabled = False

        bgrLongProcess.WorkerReportsProgress = True
        bgrLongProcess.WorkerSupportsCancellation = True
        bgrLongProcess.RunWorkerAsync()

    End Sub

    Private Sub bgrLongProcess_ProgressChanged(ByVal sender As System.Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bgrLongProcess.ProgressChanged
        'This event never called?
        Me.Text = DateTime.Now.ToString
        DataGridView1.Refresh()
    End Sub

    Private Sub bgrLongProcess_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bgrLongProcess.RunWorkerCompleted
        Button1.Enabled = True
    End Sub

    Private Sub bgrLongProcess_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgrLongProcess.DoWork
        'Do lengthy stuff here

        For Each drive In DriveInfo.GetDrives()
            If drive.DriveType = DriveType.Fixed Then
	              'To avoid "Access to the path 'C:\System Volume Information' is denied." msg
                Try
                    filelist = My.Computer.FileSystem.GetFiles(drive.ToString, FileIO.SearchOption.SearchAllSubDirectories, "Edit.*")
                    For Each filepath In filelist
                     'do stuff
                    Next filepath
                Catch Ex As UnauthorizedAccessException
                    'Ignore protected directory, and move on
                    Continue For
                End Try
            End If
        Next drive
    End Sub
End Class

Does someone know what it takes to have this event to be triggered every so often?

Thank you.
 
Thread moved to VB.Net General

You need to cause the ProgressChanged event to fire by calling bgrLongProcess.ReportProgress(Integer, Optional Object)
 
Thanks for the tip, it makes more sense... but the event is still not triggered :-/

VB.NET:
[COLOR="Blue"]Private Sub bgrLongProcess_ProgressChanged(ByVal sender As System.Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bgrLongProcess.ProgressChanged[/COLOR]
    'NO CHANGE
    Me.Text = e.UserState.ToString
    DataGridView1.Refresh()
End Sub

Private Sub bgrLongProcess_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgrLongProcess.DoWork
    For Each drive In DriveInfo.GetDrives()
        If drive.DriveType = DriveType.Fixed Then
            'To avoid "Access to the path 'C:\System Volume Information' is denied."
            Try
                filelist = My.Computer.FileSystem.GetFiles(drive.ToString, FileIO.SearchOption.SearchAllSubDirectories, "MyFiles.*")
                For Each filepath In filelist
                    DataGridView1.Rows.Add(filepath.ToString, filepath)
                    'No %tage because I don't know how many files left
                    'filepath = full path to file
                    [COLOR="Blue"]bgrLongProcess.ReportProgress(0, filepath)[/COLOR]
                Next filepath
            Catch Ex As UnauthorizedAccessException
                'Ignore protected directory, and move on

                'Does "continue for" resumes to "For Each filepath..."?
                'or "For Each drive..."?
                Continue For
            End Try
        End If
    Next drive
End Sub

Google reports something called a "delegate" but as a VB.Net newbie, I don't know if it's what I need or if it's used in other solutions to solve the UI freeze issue.

Does someone have an idea why calling ReportProgress() doesn't trigger the ProgressChanged() even?

Thank you for any hint.
 
I see you have this line in your for loop:
DataGridView1.Rows.Add(filepath.ToString, filepath)

that's causing a cross thread call and thus you have to delegate it. An easy way around that without getting into delegation is to use the ReportProgress sub to pass the FilePath info then in the ProgressChanged event add it to the DataGridView
 
An easy way around that without getting into delegation is to use the ReportProgress sub to pass the FilePath info then in the ProgressChanged event add it to the DataGridView

Thanks, it seems to have solved the issue.

I'm surprised, though, because both ReportProgress() and ProgressChanged() belong to the BackgroundWorker control, so I would expect both routines to have no access to the UI of the calling program. I'll read up more on threading in VB.Net.

For those interested, here's some working code:
VB.NET:
Private Sub bgrLongProcess_ProgressChanged(ByVal sender As System.Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bgrLongProcess.ProgressChanged
    Me.Text = e.UserState.ToString

    DataGridView1.Rows.Add(e.UserState.ToString, "temp")
    DataGridView1.Refresh()
End Sub

Private Sub bgrLongProcess_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgrLongProcess.DoWork
    'Do lengthy stuff here
    Dim filelist As Collections.ObjectModel.ReadOnlyCollection(Of String)
    Dim filepath As String

    filelist = My.Computer.FileSystem.GetFiles("C:\Program Files\", FileIO.SearchOption.SearchAllSubDirectories, "MyFiles.*")
    For Each filepath In filelist
        bgrLongProcess.ReportProgress(0, filepath)
    Next filepath
End Sub
Thanks again.
 
The ReportProgress is simply a method and the data sent to it is automatically delegated behind the scenes for you & the ProgressChanged event is raised on the same thread as the BackgroundWorker control, which in your case is the UI thread (where your form is running).

The main reason for the BW control is so you don't have to get into Threading and Delegation, it handles it for you. However there are times when I need to delegate from the BW's DoWork thread to the UI thread anyways, which can be done, but 99.9% of the time I don't need to and the BW control saves me a lot of extra coding.
 
Back
Top