Search code examples
c#backgroundworkerprogress

Backgroundworker not updating ProgressBar although the DoWork loop is running


My program is supposed to allow the user to select multiple text files, compile the contents into a single textfile and then export it into an Excel file. I have tried using the progress bar but it only gets updated after the main loop is finished and not during it. The progress bar will jump from the min value to the max value in an instant once the loop is done. It's not slowly increasing like it suppose to. Here is my code:

public partial class Form1 : Form
{
    List<string> path = new List<string>();
    Workbook excelworkbook = new Workbook();
    Worksheet excelworksheet = new Worksheet("First sheet");
    public Form1()
    {
        InitializeComponent();
    }

    private void addfiles_Click(object sender, EventArgs e)
    {
        DialogResult dr = this.selectFiles.ShowDialog();
        path.Clear();
        if (dr == System.Windows.Forms.DialogResult.OK)
        {
            // Read the files
            foreach (String file in selectFiles.FileNames)
            {
                try
                {
                    path.Add(file);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
            numFiles.Text = path.Count.ToString();
        }
    }

    private void export_Click(object sender, EventArgs e)
    {
        export.Text = "Exporting...";
        export.Enabled = false;
        addfiles.Enabled = false;
        backgroundWorker1.RunWorkerAsync();
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        try
        {
            backgroundWorker1.ReportProgress(15);   //15% on progress bar
            string[] readText = File.ReadAllLines(path[0]);
            string[] readText_secondary;
            string filename;
            int real_length = readText.Length - 3;  //create a text file that stores contents temporarily from multiple textfiles first..later will export into an excel file
            using (StreamWriter streamWriter = new StreamWriter(string.Concat(Directory.GetCurrentDirectory(), "\\Temp_textfile.txt"), false)) //create temp text file

            {
                for (int i = 12; i <= real_length; i++)
                {
                    backgroundWorker1.ReportProgress(((i / real_length) * 75) + 15);    //suppose to update the UI here
                    streamWriter.Write(string.Concat(readText[i].Substring(4, 42)));    //initial columns
                    streamWriter.Write(string.Concat(readText[i].Substring(59, 13)));    //upperlimit column
                    if (i != 12)
                    {
                        streamWriter.Write(string.Concat(readText[i].Substring(46, 13)));   //results column
                    }
                    else if (i == 12)
                    {
                        filename = Path.GetFileNameWithoutExtension(path[0]);   //serial number column
                        streamWriter.Write(string.Concat(filename + " "));
                    }
                    for (int x = 1; x < path.Count; x++)
                    {
                        readText_secondary = File.ReadAllLines(path[x]);    //secondary files
                        if (x != (path.Count - 1))
                        {
                            if (i != 12)
                            {
                                streamWriter.Write(string.Concat(readText_secondary[i].Substring(46, 13))); //write results
                            }
                            else if (i == 12)
                            {
                                filename = Path.GetFileNameWithoutExtension(path[x]);   //write serial number header
                                streamWriter.Write(string.Concat(filename + " "));
                            }
                        }
                        else
                        {
                            if (i != 12)
                            {
                                streamWriter.WriteLine(string.Concat(readText_secondary[i].Substring(46, 13))); //write results for last column
                            }
                            else if (i == 12)
                            {
                                filename = Path.GetFileNameWithoutExtension(path[x]);   //write serial number header for last column
                                streamWriter.WriteLine(string.Concat(filename + " "));
                            }
                        }
                    }
                }
            }
            var lines = File.ReadAllLines(string.Concat(Directory.GetCurrentDirectory(), "\\Temp_textfile.txt"));
            var rowcounter = 0;
            foreach (var line in lines)
            {
                var columncounter = 0;
                backgroundWorker1.ReportProgress(90);
                string[] values = new string[200];  //extract the initial columns
                values[0] = line.Substring(0, 10); values[1] = line.Substring(11, 8); values[2] = line.Substring(20, 8); values[3] = line.Substring(29, 12); values[4] = line.Substring(42, 12);
                for (int y = 0; y < path.Count; y++)
                {
                    values[5 + y] = line.Substring((55 + (13 * y)), 13);    //extract results column
                }
                foreach (var value in values)
                {
                    excelworksheet.Cells[rowcounter, columncounter] = new Cell(value);  //write column by column
                    columncounter++;
                }
                rowcounter++;
            }
            excelworkbook.Worksheets.Add(excelworksheet);   //create the excel file from object
            string timedate = DateTime.Now.ToString("dd-MM-yyyy");
            string excel_name = "\\ExportedData_" + timedate;
            int counter = 1;
            string new_path = string.Concat(Directory.GetCurrentDirectory() + excel_name + ".xls"); //this part is to prevent overwriting
            while (File.Exists(new_path))
            {
                new_path = string.Concat(Directory.GetCurrentDirectory() + excel_name + "(" + counter + ")" + ".xls");
                counter++;
            }
            excelworkbook.Save(new_path);   //save into path

            if (File.Exists(string.Concat(Directory.GetCurrentDirectory(), "\\Temp_textfile.txt"))) //delete temporary text file
            {
                File.Delete(string.Concat(Directory.GetCurrentDirectory(), "\\Temp_textfile.txt"));
            }
            backgroundWorker1.ReportProgress(100);
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error occurred!\n" + ex, "Error Window", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            addfiles.Text = "Add Files";
            export.Text = "Export!";
            numFiles.Clear();
            addfiles.Enabled = true;
            export.Enabled = true;
        }
    }

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        progressBar1.Value = e.ProgressPercentage;
    }

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        MessageBox.Show("Done exporting!", "Notification Window", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
        addfiles.Text = "Add Files";
        export.Text = "Export!";
        numFiles.Clear();
        addfiles.Enabled = true;
        export.Enabled = true;
    }
}

I cant seem to what's the problem here. Can someone point me to the right direction?


Solution

  • backgroundWorker1.ReportProgress(((i / real_length) * 75) + 15);
    

    The issue is that (i / real_length) returns 0 since you are using integer division.

    Instead you need to do:

    backgroundWorker1.ReportProgress((int)((((double)i / real_length) * 75) + 15));
    

    or:

    backgroundWorker1.ReportProgress(i * 75 / real_length + 15);
    

    I would recommend the former.