C# update and append textbox value using backgroundworker process

Peter Tirrell picture Peter Tirrell · Jul 21, 2010 · Viewed 32.6k times · Source

I've got a c# windows form app I threw together. It's fairly simple:\

inputs:

  • text string
  • source folder path
  • destination folder path
  • integer count

The app searches through text files in the source folder for the entered text string; if it finds the string then it copies that file and an image file with the same name to the destination folder. It does this however many times based on the integer input.

So I have a button, and in the button click event I call

ProcessImages(tbDID.Text, tbSource.Text, tbDest.Text, comboBoxNumberImages.SelectedItem.ToString());

which is:

private void ProcessImages(string DID, string SourceFolder, string DestFolder, string strNumImages)
        {         
            int ImageCounter = 0;
            int MaxImages = Convert.ToInt32(strNumImages);

            DirectoryInfo di = new DirectoryInfo(SourceFolder);

            foreach (FileInfo fi in di.GetFiles("*.txt"))
            {
                if (fi.OpenText().ReadToEnd().Contains(DID))
                {
                    //found one!
                    FileInfo fi2 = new FileInfo(fi.FullName.Replace(".txt", ".tif"));
                    if (fi2.Exists)
                    {
                        try
                        {
                            tbOutput.Text += "Copying " + fi2.FullName + " to " + tbDest.Text + "\r\n";
                            fi2.CopyTo(tbDest.Text + @"\" + fi2.Name, true);
                            tbOutput.Text += "Copying " + fi.FullName + " to " + tbDest.Text + "\r\n";
                            fi.CopyTo(tbDest.Text + @"\" + fi.Name, true);

                            ImageCounter++;
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message);
                        }
                    }
                }

                if (ImageCounter >= MaxImages)
                    break;

            }

        }

What happens is that the process runs fine, but I want to update a textbox on the form with progress as the files are copied. Basically the form blanks out while it's running, and after it's finished the output is in the textbox. I'd like to implement a BackgroundWorker get it to update the UI while it's running.

I've looked through the examples but am not really following them. I don't have a percentage complete value, I just want to update .Text changes each iteration and have it display. I don't even think I necessarily need to put the actual copying action in different threads, it just sounds like that needs to be run separately from the main UI thread. Maybe I'm over complicating this altogether...can someone push me in the right direction? Thanks!

Answer

Ryan from Denver picture Ryan from Denver · Jul 21, 2010

You are on the right track with the background worker. Here is an example I put together to show you how to do this. Create a new windows app with Form1. Add 4 controls to it: label1, backgroundWorker1, button1, and button2. Then use this code-behind. Then you can use the ReportProgress userState to report back to the main thread whatever you want. In this example, I am passing a string. The ProgressChanged event handler is then on the UI thread, and updates the textbox.

    public partial class Form1 : Form
{
    int backgroundInt;
    public Form1()
    {
        InitializeComponent();
        backgroundWorker1.WorkerReportsProgress = true;
    }

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        label1.Text = e.UserState as string;
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        backgroundInt = 1;
        while (backgroundWorker1.CancellationPending == false)
        {
            System.Threading.Thread.Sleep(500);
            backgroundWorker1.ReportProgress(0, 
                String.Format("I found file # {0}!", backgroundInt));
            backgroundInt++;
        }
    }


    private void button1_Click(object sender, EventArgs e)
    {
        backgroundWorker1.RunWorkerAsync();
    }

    private void button2_Click(object sender, EventArgs e)
    {
        backgroundWorker1.CancelAsync();
    }
}