Firdavs Kurbonov
Firdavs Kurbonov

Reputation: 1252

BackgroundWorker's progress bar is not working

The BackgroundWorker's progressbar is not updated while doing some tasks. What I would like to reach is progressbar moving while iterating through each file in DirectoryInfo. Suppose we have 20 files of ".sql" while first file completed it should be 5%, 10% and etc. Here is my code.

private void CSV_Click(object sender, RoutedEventArgs e)
        {         
            try
            {
                btnExtract.IsEnabled = false;
                workerextract.RunWorkerAsync();

        }
        catch (Exception ex)
        {
            System.Windows.MessageBox.Show(ex.Message);
        }
    }

    private void workerextract_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
    {
        try
        {
           this.Dispatcher.Invoke(() =>
            {

                DirectoryInfo di = new DirectoryInfo(txtQueryfolder.Text);
                files = di.GetFiles("*.sql").Count();
                currentfile = 0;

                foreach (FileInfo fi in di.GetFiles("*.sql"))
                {
                    // Open the text file using a stream reader.
                    using (StreamReader sr = new StreamReader(fi.FullName))
                    {
                        // Read the stream to a string, and write the string to the console.
                        string line = sr.ReadToEnd();

                        //System.Windows.MessageBox.Show(line);
                        ExtractToCSV(line, System.IO.Path.GetFileNameWithoutExtension(fi.Name));
                        currentfile++;
                    }
                    int percentage = (currentfile + 1) * 100 / files;
                    workerextract.ReportProgress(percentage);
                }

            });

        }
        catch(Exception ex)
        {
            System.Windows.MessageBox.Show(ex.Message);
        }
    }

    private void workerextract_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
    {
        progressBarExtract.Value = e.ProgressPercentage;
    }

    private void workerextract_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        btnExtract.IsEnabled = true;
        System.Windows.MessageBox.Show("CSV Data extraction finished!");
    }

I found that

private void workerextract_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)

is called once at the end when 100%. Also,

private void workerextract_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)

never called as I do not see Message Box at the end.

So, I think I am doing something wrong here, could you please direct me on right way?

Upvotes: 2

Views: 259

Answers (2)

Omar Muscatello
Omar Muscatello

Reputation: 1301

Using this.Dispatcher.Invoke in the BackgroundWorker's DoWork event you are executing the whole operation in the UI thread; which is what BackgroundWorker born to avoid to do.

Also, you get an error unwrapping your code from the dispatcher because you are accessing an UI object, which is txtQueryfolder.

Just use:

private void workerextract_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
    string queryFolder = e.Argument.ToString();
    try
    {
        DirectoryInfo di = new DirectoryInfo(queryFolder);
        files = di.GetFiles("*.sql").Count();
        currentfile = 0;

        foreach (FileInfo fi in di.GetFiles("*.sql"))
        {
            // Open the text file using a stream reader.
            using (StreamReader sr = new StreamReader(fi.FullName))
            {
                // Read the stream to a string, and write the string to the console.
                string line = sr.ReadToEnd();

                //System.Windows.MessageBox.Show(line);

                // ExtractToCSV shouldn't access to a UI object.
                ExtractToCSV(line, System.IO.Path.GetFileNameWithoutExtension(fi.Name));
                currentfile++;
            }
            int percentage = (currentfile + 1) * 100 / files;
            workerextract.ReportProgress(percentage);
        }
    }
    catch (Exception ex)
    {
        // Don't use MessageBox in a thread different from the UI one. Just set the result (e.Result) and get that in the RunWorkerCompleted event.
        // System.Windows.MessageBox.Show(ex.Message);
    }
}

When you call the RunWorkerAsync method just add the parameter like below:

workerextrac.RunWorkerAsync(txtQueryfolder.Text);

Upvotes: 0

Firdavs Kurbonov
Firdavs Kurbonov

Reputation: 1252

The problem was in wrapping whole DoWork inside Dispatcher.Invoke. I need to wrap only those code where it is interacting with UI. So I changed the code appropriately and it works.

 private void workerextract_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            try
            {
                this.Dispatcher.Invoke(() =>
                {
                    di = new DirectoryInfo(txtQueryfolder.Text);
                });
                    files = di.GetFiles("*.sql").Count();
                    currentfile = 0;

                foreach (FileInfo fi in di.GetFiles("*.sql"))
                {
                    // Open the text file using a stream reader.
                    using (StreamReader sr = new StreamReader(fi.FullName))
                    {
                        // Read the stream to a string, and write the string to the console.
                        string line = sr.ReadToEnd();

                        this.Dispatcher.Invoke(() =>
                        {
                        //System.Windows.MessageBox.Show(line);
                        ExtractToCSV(line, System.IO.Path.GetFileNameWithoutExtension(fi.Name));
                        });

                        currentfile++;
                    }
                    int percentage = (currentfile + 1) * 100 / files;
                    workerextract.ReportProgress(percentage);
                }
        }
        catch(Exception ex)
        {
            System.Windows.MessageBox.Show(ex.Message);
        }
    }

Thanks to all for showing the direction.

Upvotes: 0

Related Questions