Simos Sigma
Simos Sigma

Reputation: 978

ProgressBar not updating using a For Each loop

I'm copying all the .avi and .png files from one folder into another:

Private Sub CopierSend_Button_Click(sender As Object, e As EventArgs) Handles CopierSend_Button.Click

    If MessageBox.Show("Click OK to send media or just Cancel.", "Media Copier", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) = DialogResult.OK Then
        For Each foundFile As String In My.Computer.FileSystem.GetFiles(FrapsFolder_, Microsoft.VisualBasic.FileIO.SearchOption.SearchTopLevelOnly, "*.avi", "*.png")
            Dim foundFileInfo As New System.IO.FileInfo(foundFile)
            My.Computer.FileSystem.CopyFile(foundFile, DestFolder_ & foundFileInfo.Name, Microsoft.VisualBasic.FileIO.UIOption.OnlyErrorDialogs, Microsoft.VisualBasic.FileIO.UICancelOption.DoNothing)
        Next
    Else
        'Nothing Yet
    End If

End Sub

I want to add a ProgressBar which will count every time a file is copied, so I added this code before the For Each loop:

Dim file1() As String = IO.Directory.GetFiles(FrapsFolder_, "*.avi")
Dim file2() As String = IO.Directory.GetFiles(FrapsFolder_, "*.png")
Dim files = file1.Length + file2.Length
Copier_ProgressBar.Step = 1
Copier_ProgressBar.Maximum = files

And added this code inside the For Each loop:

Copier_ProgressBar.Value += 1

Here is all of my code:

Private Sub CopierSend_Button_Click(sender As Object, e As EventArgs) Handles CopierSend_Button.Click

    If MessageBox.Show("Click OK to send media or just Cancel.", "Media Copier", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) = DialogResult.OK Then

        Dim file1() As String = IO.Directory.GetFiles(FrapsFolder_, "*.avi")
        Dim file2() As String = IO.Directory.GetFiles(FrapsFolder_, "*.png")
        Dim files = file1.Length + file2.Length
        Copier_ProgressBar.Step = 1
        Copier_ProgressBar.Maximum = files

        For Each foundFile As String In My.Computer.FileSystem.GetFiles(FrapsFolder_, Microsoft.VisualBasic.FileIO.SearchOption.SearchTopLevelOnly, "*.avi", "*.png")
            Dim foundFileInfo As New System.IO.FileInfo(foundFile)
            My.Computer.FileSystem.CopyFile(foundFile, DestFolder_ & foundFileInfo.Name, Microsoft.VisualBasic.FileIO.UIOption.OnlyErrorDialogs, Microsoft.VisualBasic.FileIO.UICancelOption.DoNothing)
            Copier_ProgressBar.Value += 1
        Next

    Else

        'Nothing Yet

    End If
End Sub

The ProgressBar updates, but only after all the files have been copied instead of updating in real time. Any idea?

Upvotes: 1

Views: 1398

Answers (1)

Bugs
Bugs

Reputation: 4489

As it stands it looks like the ProgressBar doesn't do anything until after all the files have copied. That isn't strictly true. Instead your UI is not updating.

Instead you should look into using a BackgroundWoker to report progress. Something like this should do the trick:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    'This can also be set using the Designer
    BackgroundWorker1.WorkerReportsProgress = True

End Sub

Private Sub CopierSend_Button_Click(sender As Object, e As EventArgs) Handles CopierSend_Button.Click

    If MessageBox.Show("Click OK to send media or just Cancel.", "Media Copier", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) = DialogResult.OK Then
        Dim file1() As String = IO.Directory.GetFiles(FrapsFolder_, "*.avi")
        Dim file2() As String = IO.Directory.GetFiles(FrapsFolder_, "*.png")
        Dim files As Integer = file1.Length + file2.Length

        Copier_ProgressBar.Step = 1
        Copier_ProgressBar.Maximum = files       

        BackgroundWorker1.RunWorkerAsync()
    End If

End Sub

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

    For Each foundFile As String In My.Computer.FileSystem.GetFiles(FrapsFolder_, Microsoft.VisualBasic.FileIO.SearchOption.SearchTopLevelOnly, "*.avi", "*.png")
        Dim foundFileInfo As New System.IO.FileInfo(foundFile)
        My.Computer.FileSystem.CopyFile(foundFile, DestFolder_ & foundFileInfo.Name, Microsoft.VisualBasic.FileIO.UIOption.OnlyErrorDialogs, Microsoft.VisualBasic.FileIO.UICancelOption.DoNothing)
        BackgroundWorker1.ReportProgress(Copier_ProgressBar.Value + 1)
    Next

End Sub

Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged

    Copier_ProgressBar.Value = e.ProgressPercentage

End Sub

As an additional note, for best practice, I would consider using Path.Combine instead of concatenating strings together:

My.Computer.FileSystem.CopyFile(foundFile, Path.Combine(DestFolder_, foundFileInfo.Name), Microsoft.VisualBasic.FileIO.UIOption.OnlyErrorDialogs, Microsoft.VisualBasic.FileIO.UICancelOption.DoNothing)

Upvotes: 1

Related Questions