Search code examples
c#csvbackgroundworker

How to use BackgroundWorker to show progress of reading CSV file


I have a very large CSV file (~5.5GB) which I am trying to read to show row count to see how long it takes to complete the process. The issue I am having is since it is a large file, whenever I try to read the file my application hangs, could be that it's busy reading or just frozen. So I want to integrate a background worker to show progress in my application.

I have a ProgressBar (pb), a Label (label1), a TextBox (textBox1), and a Button (button)

My application code looks like the following:

private void Form1_Load(object sender, EventArgs e)
{
     textBox1.Text = @"\\svr\CreFiles\ndaa_2011.csv";
}

private void button1_Click(object sender, EventArgs e)
{
     int i = 0;
     BackgroundWorker worker;
     worker = new BackgroundWorker { WorkerReportsProgress = true };
     worker.DoWork += (senders, args) =>
     {
       using (TextFieldParser parser = new TextFieldParser(textBox1.Text))
       {
            parser.TextFieldType = FieldType.Delimited;
            parser.SetDelimiters(",");
            while (!parser.EndOfData)
            {
                  //Processing row
                  string[] fields = parser.ReadFields();
                  foreach (string field in fields)
                  {
                       //TODO: Process field
                       i++; //add 1 to i for each row to get a total row count
                       label1.Invoke((MethodInvoker) delegate
                       {
                           label1.Text = "" + i;
                       });
                       worker.ReportProgress(i); //maybe the calculation needs to be different?
                  }
            }
       }
    };
    worker.ProgressChanged += (senders, args) =>
    {
       pb.Value = Math.Min(args.ProgressPercentage, 100); //maybe this needs to change?
    };
    worker.RunWorkerAsync();
}

I ran the application and I don't see any change in the ProgressBar.

What I am looking to do is no matter the number of rows the progress should change from 0 to 100% based on the row count.

Does my code need to be modified in any way?

Update:

I updated my question and added the label and the background worker progress inside the foreach statement and the label is changing showing how many rows it's reading. But how do I find the calculation for the progress? The progressbar fills up as soon as I hit the button.


Solution

  • First of all, you are using i value (i.e. the line number) to report the progress of the application, which unless the file is exactly 100 lines long, would produce the wrong percentage computation.

    The only indication of how long the job would take is the length of the file you are processing; however, this length is in bytes and each line does not exactly correspond to a specific number of bytes. You can compute the number of bytes each string line has base on the fact each char takes about a byte using ASCII encoding (this changes in Unicode, which might be 1, 2, or 4 bytes per char). You can use that value to update the percentage based on the cumulative sum and the length of the file.