0

I am trying to create a tool to search data from multiple .txt files. I want to create a progress bar for the user to track the progress of the work. Here's what I got

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    String terms;
    StringBuilder sb;
    if (filePath != "")
    {
        sb = new StringBuilder();
        //I use another function to add path to string filePath, 
        //seperated by \r\n
        String[] fpath = filePath.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
        foreach (string path in fpath)
        {
            if (!String.IsNullOrEmpty(path))
            {                     
                lines = File.ReadAllLines(path);
                for (int i = 0; i < lines.Count(); i++)
                {
                    terms = lines[i];
                    if (terms.Contains("Content to look for"))
                    {
                        sb.AppendLine(lines[i]);                                
                    }
                    //Problem here
                    backgroundWorker1.ReportProgress(i);
                }
            }
        }
    }
}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar1.Value += (progressBar1.Maximum * e.ProgressPercentage / 100);
    lblPercent.Text = e.ProgressPercentage.ToString() + " %";
}

When I add line:

backgroundWorker1.ReportProgress(i);

It throws exception:

An unhandled exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll

I tried to use Ivoke but it still throws this exception:

Invoke((Action)(() =>
{
    String terms;
    StringBuilder sb;
    if (filePath != "")
    {
        sb = new StringBuilder();
        String[] fpath = filePath.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
        foreach (string path in fpath)
        {
            if (!String.IsNullOrEmpty(path))
            {
                lines = File.ReadAllLines(path);
                for (int i = 0; i < lines.Count(); i++)
                {
                    terms = lines[i];
                    if (terms.Contains("Content to look for"))
                    {
                        sb.AppendLine(lines[i]);
                    }
                    backgroundWorker1.ReportProgress(i);
                }
            }
        }
    }
}));

Can you tell me where I am wrong?

Lee
  • 11
  • 3
  • 1
    Are you sure that you never call `ReportProgress` with argument, greater than 100? As your argument `i` is just a line number, it can easily be more then 100. – Serg Nov 26 '21 at 03:51
  • 1
    Also, make sure that `backgroundWorker1.WorkerReportsProgress = true` and check `InnerException` of your `TargetInvocationException` as it can contain more details. – Serg Nov 26 '21 at 03:53
  • The `TargetInvocationException` wraps the actual exception that is thrown. You need to check the `InnerException` to determine the cause of the throw. – Codehack Nov 26 '21 at 03:54
  • `progressBar1.Value +=` this will increase the `Value`, not just assign it. Is this your intention? – Theodor Zoulias Nov 26 '21 at 04:00
  • 1
    As a side note, the `BackgroundWorker` is no longer the coolest tool in the toolbox. After the advent of the async/await technology, it is now considered a [technologically obsolete](https://stackoverflow.com/questions/12414601/async-await-vs-backgroundworker/64620920#64620920) class. – Theodor Zoulias Nov 26 '21 at 04:02
  • @Serg: I ​​have set backgroundWorker1.WorkerReportsProgress = true. As you said, the number of lines depends on the number of files and it can be greater than 100. I set a try-catch to catch InnerException but it still throws the TargetInvocationException. – Lee Nov 26 '21 at 06:20
  • 1
    Your problem is the ProgressBar. You report greater than the Maximum as mentioned in the first comment. Instead. report the processed files (outer loop) instead of the lines of each file. You'll need to invoke `ProgressBar.Maximum = fpath.Length` before the outer loop. And get rid of the last code block. The `ProgressChanged` runs in the UI thread. As noted. async/await is much better approach. – dr.null Nov 26 '21 at 06:21
  • @TheodorZoulias: i want the progress bar to perform step with unknown maximum value . Did I use it the wrong way? – Lee Nov 26 '21 at 06:24
  • 1
    My suggestion is to handle the [`RunWorkerCompleted`](https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.backgroundworker.runworkercompleted) event, and inside the handler observe the [`Error`](https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.asynccompletedeventargs.error) property of the `e` argument. This will show you the real error, and you'll be able to act accordingly. – Theodor Zoulias Nov 26 '21 at 08:33

0 Answers0