Amrit Sharma
Amrit Sharma

Reputation: 1916

Background worker to copy directory

In my Windows Form Application, certain directories are copied on user request. Currently copying these directories is running on UI thread as a result, I am not able see any progress of the process.

Currently the copy function is trigger my following code.

 private void button5_Click(object sender, EventArgs e)
        {


            string[] str = comboBox2.Text.Split(' ');
            string username = str[2].Replace("[", "").Replace("]", "");
            label3.Text = comboBox3.Text;
            DialogResult result = MessageBox.Show("Do you want to copy " + comboBox3.Text + " mozilla profile for " + username + " to Selected Servers?", "Confirmation", MessageBoxButtons.YesNoCancel);
            if (result == DialogResult.Yes)
            {
                if (myCheck.Checked == true)
                {
                    string path = getPath(comboBox3.Text);
                    try
                    {      
                        string source = path + "\\Appdata";
                        string dest = "\\\\192.168.1.40\\C$\\Users\\" + username + "\\AppData\\Local\\Mozilla";
                        Copy(@source, @dest);

                    }
                 }
             }
        }

Copy functions has following Code.

     public void Copy(string sourceDirectory, string targetDirectory)
                {

                    DirectoryInfo diSource = new DirectoryInfo(sourceDirectory);
                    DirectoryInfo diTarget = new DirectoryInfo(targetDirectory);
                    //Gets size of all files present in source folder.
                    GetSize(diSource, diTarget);
                    maxbytes = maxbytes / 1024;

                    progressBar1.Maximum = maxbytes;
                    CopyAll(diSource, diTarget);
                }

 public void CopyAll(DirectoryInfo source, DirectoryInfo target)
            {

                if (Directory.Exists(target.FullName) == false)
                {
                    Directory.CreateDirectory(target.FullName);
                }
                foreach (FileInfo fi in source.GetFiles())
                {

                    fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true);

                    total += (int)fi.Length;

                    copied += (int)fi.Length;
                    copied /= 1024;
                    progressBar1.Visible = true;
                    progressBar1.Step = copied;

                    progressBar1.PerformStep();
                    label14.Visible = true;
                    label14.Text = (total / 1048576).ToString() + "MB of " + (maxbytes / 1024).ToString() + "MB copied";



                    label14.Refresh();
                }

                foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
                {



                    DirectoryInfo nextTargetSubDir = target.CreateSubdirectory(diSourceSubDir.Name);
                    CopyAll(diSourceSubDir, nextTargetSubDir);
                }
            }

            public void GetSize(DirectoryInfo source, DirectoryInfo target)
            {


                if (Directory.Exists(target.FullName) == false)
                {
                    Directory.CreateDirectory(target.FullName);
                }
                foreach (FileInfo fi in source.GetFiles())
                {
                    maxbytes += (int)fi.Length;//Size of File


                }
                foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
                {
                    DirectoryInfo nextTargetSubDir = target.CreateSubdirectory(diSourceSubDir.Name);
                    GetSize(diSourceSubDir, nextTargetSubDir);

                }

            }

My code is working perfectly but i am not able to see the progress and not able to see the update in Label.

Can somebody help me to run this copy in new thread so that I can see the progress in progress bar.

Upvotes: 1

Views: 3742

Answers (3)

Sunil
Sunil

Reputation: 3424

Try this pseudo code:

BackgroundWorker bw = new BackgroundWorker();    
bw.WorkerSupportsCancellation = true;    
bw.WorkerReportsProgress = true;

bw.DoWork += 
new DoWorkEventHandler(bw_DoWork);
bw.ProgressChanged += 
new ProgressChangedEventHandler(bw_ProgressChanged);
bw.RunWorkerCompleted += 
new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);

private void button5_Click(object sender, EventArgs e)
{
      // rest of the code above this...
      if (bw.IsBusy != true)
      {
          bw.RunWorkerAsync();
      }
}

private void bw_DoWork(object sender, DoWorkEventArgs e)
{  
     // rest of the code above this...
     Copy(@source, @dest);
}

private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
     progressBar1.Visible = true;
     progressBar1.Step = copied;

     progressBar1.PerformStep();
}

private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
      MessageBox.Show("Completed");
}

Upvotes: 0

Mikko Viitala
Mikko Viitala

Reputation: 8404

Not going to wrap it up for you but I think the following might get you on the right track. Given you have "standard" :) button1 and progressBar1 you get nice non-blocking UI update using e.g. Task and BeginInvoke().

private void button1_Click(object sender, EventArgs e)
{
    progressBar1.Minimum = 0;
    progressBar1.Maximum = 5;

    Task.Factory.StartNew(() =>
        {
            for (int i = 0; i <= 5; i++)
            {
                int progress = i;
                progressBar1.BeginInvoke((Action)(() =>
                    {
                        progressBar1.Value = progress;
                    }));
                Thread.Sleep(250);
            }
        });
}

Upvotes: 0

user4259788
user4259788

Reputation: 147

Here's a simple example to use background worker.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        Shown += new EventHandler(Form1_Shown);

        // To report progress from the background worker we need to set this property
        backgroundWorker1.WorkerReportsProgress = true;
        // This event will be raised on the worker thread when the worker starts
        backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
        // This event will be raised when we call ReportProgress
        backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
    }
    void Form1_Shown(object sender, EventArgs e)
    {
        // Start the background worker
        backgroundWorker1.RunWorkerAsync();
    }
    // On worker thread so do our thing!
    void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        // Your background task goes here
        for (int i = 0; i <= 100; i++)
        {
            // Report progress to 'UI' thread
            backgroundWorker1.ReportProgress(i);
            // Simulate long task
            System.Threading.Thread.Sleep(100);
        }
    }
    // Back on the 'UI' thread so we can update the progress bar
    void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        // The progress percentage is a property of e
        progressBar1.Value = e.ProgressPercentage;
    }
}

You can do the CopyAll in Do_Work and Report progress to show the progress on UI in a progress bar.

Upvotes: 1

Related Questions