adding a progress bar

2019-03-02 07:19发布

问题:

I have an a windows form application that use one class (its name is Parser) this form has a button and when i click on the windows form application button it call one of the parser class method .

this method simply read text file line after line and write each line to separate file...

i would like to add a progress bar to the form in order to show the progress( it is a very large file )

any idea how to do that? I have in the Parse class 2 property one for the number of line in the file and the second how much lines already checked.

here is my button2_Click function

private void button2_Click(object sender, EventArgs e)
{
      if (this.textBox1 != null & this.textBox2 != null)
      {
           inst.init(this.textBox1.Text, this.textBox2.Text);
           //this.progressBar1.Show();

           inst.ParseTheFile();
           System.Windows.Forms.MessageBox.Show("Parsing finish successfully"); 
       }
}

回答1:

You could do:

private void button1_Click(object sender, EventArgs e)
{
    ThreadPool.QueueUserWorkItem((obj) =>
    {
        var lines = File.ReadLines(@"D:\test.txt");
        var count = lines.Count();

        for(int i = 0; i < count; i++)
        {
            // some parse work
            Invoke(new Action(() =>
            {
                progressBar1.Value = (i * 100) / count;
            }));
        }
    });
}

In the example above, it simply creates a background thread in order not to block the UI thread, until the Invoke method is called. The Invoke method is necessary, in order to manipulate with a Control that the current thread isn't the owner of. It takes a delegate, and runs this delegate on the thread that owns the Control.

You could even go as far, as making the foreach loop parallel, if it's a time consuming task to parse the lines. An example:

private void button1_Click(object sender, EventArgs e)
{
    ThreadPool.QueueUserWorkItem((obj) =>
    {
        var lines = File.ReadLines(@"D:\test.txt");
        var count = lines.Count();

        Parallel.For(0, count, i =>
        {
            // some parse work
            Invoke(new Action(() =>
            {
                progressBar1.Value = (i * 100) / count;
            }));
        });
    });
}


回答2:

normaly you should go on and write some on what you allready tried. As I think you are more on the *begining" side I would advise looking into the BackgroundWorker and its ProgressChanged event / system (Here is a intro to it).

Of course you have to move your ParseTheFile-code into this.

For more advanced stuff there are a few options:

  • add a parameter to the ParseTheFile (for example a Action) that is used to set the progress
  • return a IObservable from your ParseTheFile that indicates the progress
  • use some static service ParseTheFile is using to indicate the progress (not adviced)
  • ... (I'm sure other poeple will find a lot more options)

(Please not that most of this options require to use Control.Invoke to get back to your UI-Thread for setting progress-bars value if you use another thread - and I would advise you using another thread if the file is that big)

For starter I would go with the backgroundworker - IMHO it's fine if you don't want to go SOLID (desing patterns/priciples) on your first run ;)



回答3:

Just use Math to Calculate Percentage Like :

//While Reading
NumOfLines++;
int Percentage = (NumOfLines * 100) / TotalLines ;
ProgressBar.Value = Percentage;

And probably put int.ParseTheFile(); into a Background Worker and/or within a Thread.