Search code examples
c#winformsclickbackgroundworker

How to add a piece of code to a backgroundWorker that is triggered by click?


I need to work with a lot of file.copy, this makes my form1 "not responding" and my program show DeadLock exception, so I want to create a backgroundWorker to handle all the main processing. What I did:

Button:

if (backgroundWorker1.IsBusy != true)
            {
                backgroundWorker1.RunWorkerAsync();
            }

DoWork:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;
        bool continueWork = true;

        while (continueWork)
        {
            if ((worker.CancellationPending == true))
            {
                e.Cancel = true;
                break;
            }
            else
            {
                foreach (string name in listFiles) //global list
                {
                    string destwithFilename= dest + "\\" + Path.GetFileName(name);
                    try
                    { File.Copy(name, destwithFilename, false);}
                    catch (Exception EX_NAME)
                    {
                        Console.WriteLine(EX_NAME);
                    }
                    worker.ReportProgress((1));
                }
                pbStatus.Increment(50); //Error, I can't access form1, another thread.
                continueWork = false; //If job is done, break;
                System.Threading.Thread.Sleep(500);
            }
        }
    }

Problems:

1) Form1 still appear as "Not responding";

2) Form1 can't be accessed;

3) Even with a backgroundWorker, DeadLock exception still appears. //Maybe I should disable Managed Debug Assistants

EDIT

DoWork

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;
        bool continueWork = true;

        while (continueWork)
        {
            foreach (string name in Files) //Global
            {
                if ((worker.CancellationPending == true))
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    string destwithFilename= dest + "\\" + Path.GetFileName(name);
                    try
                    {
                        File.Copy(name, destwithFilename, false); //no overwritting
                        worker.ReportProgress((1));
                        //System.Threading.Thread.Sleep(50);
                    }
                    catch (Exception EX_NAME)
                    {
                        Console.WriteLine(EX_NAME);
                    }
                }
            }
            continueWork = false;
        }
    }

ProgressChanged:

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        pbProcess.Value = e.ProgressPercentage;
        if (pbProcess.Value == pbProcess.Maximum)
        {
            cbFinal.Checked = true;
        }
    }

Result:

Output is really slow, but now my form continue the work without "not responding". pbProcess does not increment, I'm not sure why. pbProcess is a progressBar.


Solution

  • To report the progression, you should :

    • Set the WorkerReportsProgress property to True
    • Report the progress using the ReportProgress() method of the backgroun worker
    • And then, handle the ProgressChanged event of your background worker. and set the value of your pbStatus

    Code :

    Report the progression

    backgroundWorker1.ReportProgress(50);
    

    Handle the ProgressChanged event

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

    Progression

    And for progression, you are reporting the progression using ReportProgress(1), this set the value of your progress bar to one, and does not increment it by 1

    int cpt = 1;
    int totalFilesCount = listFiles.Count;
    
    foreach (var field in listFiles)
    {
          // Copy the file ...
    
          backgroundWorker1.ReportProgress((cpt / totalFilesCount) * 100);
          cpt++;
    }