简体   繁体   English

BackgroundWorker不报告文件复制进度吗?

[英]BackgroundWorker doesn't report filecopy progress?

I am making and app using C# and Winforms that archives and saves folders to specified locations,for archiving folders i have a BackgroundWorker which takes as input a folder path and generates a zip archive.Now in the next step the file needs to be moved at specified location,again as the file is large enough and could hang up UI thread i moved the code to another BackgroundWorker named FileMove ,everything works well except that the FileMove is not reporting any progress,here is the function that i call as soon as archiving is over; 我正在使用C#和Winforms制作和应用程序,该程序将文件夹存档并保存到指定位置,对于存档文件夹,我有一个BackgroundWorker ,它将输入文件夹路径并生成一个zip存档。现在,下一步需要将该文件移动到再次指定位置,因为文件足够大并且可能挂断UI线程,我将代码移到了另一个名为FileMove的 BackgroundWorker上 ,一切正常,但是FileMove没有报告任何进度,这是我在存档后立即调用的功能结束了;

  private void FileMove_DoWork(object sender, DoWorkEventArgs e)
    {
        label3.Text = "Saving file,please wait...";
        File.Move(temppath + @"\Output.jpg", savefilename);
    }

    private void FileMove_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        label3.Text = "Saving file,please wait... " + e.ProgressPercentage.ToString(); //This should show Progress Percentage but it doesn't.
    }

    private void FileMove_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        label3.Text = ("The folder has been successfully hidden.");
        button1.Enabled = true;
        button2.Enabled = true;
        button3.Enabled = true;
        this.ControlBox = true;
    }

The problem i'm facing is as soon as file moving starts label3 shows "Saving file,please wait..." and after a long time(as i'm compressing 900-1000 MB)it shows "The folder has been successfully hidden.".During ProgressChanged event label should also show Percentage but it doesn't.Please point out or correct where i've gone wrong.Any help will be appreciated. 我面临的问题是,文件移动开始后, label3会显示“正在保存文件,请稍候...”,经过很长一段时间(因为我正在压缩900-1000 MB),它显示“文件夹已成功隐藏。“。在ProgressChanged事件标签中,事件标签也应显示百分比,但不显示。请指出或更正我出了错的地方。任何帮助将不胜感激。

First, your BackgroundWorker is trying to update the UI from its background thread, which is a no-no in multithreaded UI apps. 首先,您的BackgroundWorker尝试从其后台线程更新UI,这在多线程UI应用程序中是不行的。

To update the UI you'll need it to switch to the UI thread to do the update. 要更新UI,您需要将其切换到UI线程进行更新。 This is done by first checking if the label3.InvokeRequired is true (indicating you can't update the UI from the current thread), then passing a delegate to label3.Invoke ( not Delegate.Invoke() ) 首先通过检查label3.InvokeRequired是否为真(指示您无法从当前线程更新UI),然后将委托传递给label3.Invokenot Delegate.Invoke() )来完成此操作。

This is a pattern you need to be very familiar with for WinForms development. 对于WinForms开发,您需要非常熟悉这种模式。 The Control.Invoke MSDN page includes a sample of leveraging this pattern. Control.Invoke MSDN页面包括利用此模式的示例。

Second, you need to call BackgroundWorker.ReportProgress() periodically, which fires the ProgressChanged event with a percentage-complete value. 其次,您需要定期调用BackgroundWorker.ReportProgress() ,这将触发具有百分比完成值的ProgressChanged事件。


Here's a sample app. 这是一个示例应用程序。 It assumes you've got a Form with a Button, a Label, and a BackgroundWorker with WorkgerReportsProgress = true (and WorkerSupportsCancellation = true , for bonus points). 假设您有一个带有按钮,标签和带有WorkgerReportsProgress = true的BackgroundWorker(以及加分的WorkerSupportsCancellation = true )的BackgroundWorker。

When you click the button it starts a 5-second blocking task, then switches to 10 1-second blocking tasks (reporting progress along the way). 当您单击按钮时,它将启动一个5秒钟的阻止任务,然后切换到10个1秒钟的阻止任务(报告过程中的进度)。

Note the helper method InvokeIfRequired() that ensures the UI is updated from the correct thread. 注意帮助程序方法InvokeIfRequired() ,该方法确保从正确的线程更新UI。 There's no harm in using this excessively. 过度使用它没有害处。

public partial class Form1 : Form
{
  public Form1()
  {
    InitializeComponent();
  }

  private void button1_Click(object sender, EventArgs e)
  {
    if (backgroundWorker1.IsBusy)
    {

      label1.Text = "Reset!";
      backgroundWorker1.CancelAsync();
      return;
    }

    backgroundWorker1.RunWorkerAsync();
  }

  private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
  {
    label1.InvokeIfRequired(() => label1.Text = "Gettin busy");
    System.Threading.Thread.Sleep(5000);

    for (int i = 0; i < 10; i++)
    {
      backgroundWorker1.ReportProgress(i*10);
      System.Threading.Thread.Sleep(1000);
    }
  }

  private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
  {
    label1.InvokeIfRequired(() => label1.Text = "Done");
  }

  private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
  {
    label1.InvokeIfRequired(() => label1.Text = string.Format("{0}% done", e.ProgressPercentage));
  }
}

public static class InvokeExtensions
{
  public static void InvokeIfRequired(this ISynchronizeInvoke control, MethodInvoker action)
  {
    if (control.InvokeRequired)
    {
      control.Invoke(action, null);
    }
    else
    {
      action();
    }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM