JumpingRock
JumpingRock

Reputation: 59

Updating progress bar WPF Visual studio

So my issue may sound familiar, I simply want to update a progress bar concurrently with the data that is being processed in my program.

I have two windows: StartupWindow and UpdateWindow. The Application begins by creating the startup window, the user will push a button to open the UpdateWindow. The following is the code for the button:

Private Sub btnUpdateClick(sender As Object, e As RoutedEventArgs) Handles btnUpdate.Click
    Dim updateWindow As New UpdateWindow
    updateWindow.ShowDialog()

    btnUpdate.IsEnabled = False
End Sub

With this code I got the error most other people do: "The calling thread cannot access this object because a different thread owns it."

        Private Sub updateDevice()
             Dim currPercent As Integer 
             currPercent = ((sentPackets / totalPacketsToWrite) * 100)
             progressLabel.content = currPercent.ToString + "%"
             pb.Maximum = totalPacketsToWrite
             pb.Value = sentPackets
                If sentPackets < totalPacketsToWrite Then
                    '....update....
                Else
                    MsgBox("Device now has update stored on flash!")
                    '...close everything up
                End If
        End Sub

Here are the three things I have tried so far:

  1. Use Invoke/Dispatcher/Delegate to try and seem to only be able to put the update in a different thread's queue? Can't seem to pause other the other threads to update the UI either...
  2. Implement the BackgroundWorker Class and use report progress from it, this worked but I could only update the progress bar under bw.DoWork I make a lot of calls and have responses from external devices so it would be difficult to put all my code under one function.
  3. I read somewhere that since this was the second window created (called from the original) I would have issues with it. So I took someone's solution and tried to create and entire new thread when the 'update' button was pressed ie.:

Something to note is that I added a 'cancel' button:

Private Sub buttonStart_Click(sender As Object, e As RoutedEventArgs) Handles btnStart.Click
                btnStart.IsEnabled = False
                btnStart.Visibility = Windows.Visibility.Hidden
                btnCancel.IsEnabled = True
                btnCancel.Visibility = Windows.Visibility.Visible
                beginUpdate()
    End Sub


Private Sub buttonCancel_Click(sender As Object, e As RoutedEventArgs) Handles btnCancel.Click
                btnStart.IsEnabled = True
                btnStart.Visibility = Windows.Visibility.Visible
                btnCancel.IsEnabled = False
                btnCancel.Visibility = Windows.Visibility.Hidden
                'TODO MAKE IT CANCEL
    End Sub

And every time I clicked the update/cancel button the progress bar would update. Every time I pressed the button it refreshed the progress bar to the current completion. I'm quite puzzled, I am able to update user interfaces if it is just one window... but if the user pushes a button to call a new window I cannot update anything in the second window. Any suggestions?

EDIT: I ended up making global variables that updated in my long code. Than ran backgroundworker before I did anything else and it ran asynchronous to my process, updating the progress bar:

Private Sub bw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)
            Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
            While finished = False
                Threading.Thread.Sleep(50)
                bw.ReportProgress(currPercent)
            End While
        End Sub

The start of my code was simple - like so:

Private Sub buttonStart_Click(sender As Object, e As RoutedEventArgs) Handles btnStart.Click
            bw.RunWorkerAsync()
            beginUpdate()
        End Sub

Upvotes: 0

Views: 1060

Answers (1)

Sheridan
Sheridan

Reputation: 69959

First things first... get the ProgressBar working: For this part, please read my answer to the Progress Bar update from Background worker stalling question here on Stack Overflow. Now, let's assume that you've got the basic update of a ProgressBar working... next, you want to be able to cancel the work. It is a simple matter to update the DowWork method accordingly:

private void DoWork(object sender, DoWorkEventArgs e)
{
    for (int i = 0; i <= 100; i++)
    {
        if (IsCancelled) break; // cancellation check
        Thread.Sleep(100); // long running process
        backgroundWorker.ReportProgress(i);
    }
}

So all you need to do to cancel the long running process and the ProgressBar update is to set the IsCancelled property to true.

Upvotes: 1

Related Questions