backgroundworker与进度条WPF的两个问题

时间:2016-06-01 11:21:38

标签: c# wpf multithreading backgroundworker

我使用的是WPF,我的主线程是GUI(向导)。

当用户在向导上单击“完成”时,它会打开显示后台工作程序中使用的用户进度条的第二个线程。

在我正在做的主线程中:

5

在每个createFiles方法中,我将名为currentStep的静态变量加1,我在后台worker中使用它,如下所述。

我在做后台工作者:

MessageWithProgressBar progress = new MessageWithProgressBar();
progress.Show();
createFilesInA();
createFilesInB();
createFilesInC();
createFilesInD();
createFilesInE();
createFilesInF();
createFilesInG();
createFilesInH();
createFilesInI();
createFilesInJ();
createFilesInK();

主线程更新变量名为currentStep,第二个线程用它来报告主线程进度。

主线程的操作需要几秒钟(不超过15秒)

我有两个问题:

  1. 只有当currentStep = 2(然后进度为16)然后进度为100时我才会在进度条上看到,我看不到每一步

  2. 一开始,进度条冻结,似乎卡住了。

  3. (也许它从主线程连接到调用progress.Show()?)

    谢谢!

1 个答案:

答案 0 :(得分:2)

据我了解您的代码,您的后台工作人员并没有做任何事情。它会更新进度一次,就是这样。

另外:使用全局静态变量在表单和后台工作程序之间进行通信 - 哎呀......

另外,在我看来你错了。工作(CreateFilesInA ... CreateFilesInK)应由后台工作人员完成 - 这就是它的用途。由于主线程将以您实现它的方式被阻止,否则您将看不到任何更新。

实现这样的通常方法是:

  1. 创建进度窗口并禁用UI
  2. 启动在DoWork中执行操作的后台工作程序。在DoWork中,在每次调用CreateFilesInXYZ方法后,请致电ReportProgress更新UI。
  3. 每当ProgressChanged事件被触发时更新正在进行中的内容
  4. 隐藏进度窗口并在后台工作完成后启用应用程序的UI
  5. 你这样做的方式绝不是异步的。实际上,您的代码看起来应该是这样的:

    public partial class MainWindow : Window
    {
        private BackgroundWorker backgroundWorker = new BackgroundWorker();
        private MessageWithProgressBar progressWindow;
    
        public MainWindow()
        {
            InitializeComponent();
            backgroundWorker.WorkerReportsProgress = true;
            backgroundWorker.ProgressChanged += ProgressChanged;
            backgroundWorker.DoWork += DoWork;
            backgroundWorker.RunWorkerCompleted += BackgroundWorker_RunWorkerCompleted;
        }
    
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            progressWindow = new MessageWithProgressBar();
            progressWindow.Owner = this;
            progressWindow.Show();
    
            backgroundWorker.RunWorkerAsync();
        }
    
    
        private void DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = (BackgroundWorker)sender;
            int numSteps = 11;
            int currentStep = 0;
            int progress = 0;
    
            CreateFilesInA();
            currentStep += 1;
    
            progress = (int)((float)currentStep / (float)numSteps * 100.0);
            worker.ReportProgress(progress);
    
            CreateFilesInB();
            currentStep += 1;
    
            progress = (int)((float)currentStep / (float)numSteps * 100.0);
            worker.ReportProgress(progress);
    
            // All other steps here
            ...
        }
    
        private void ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressWindow.progress.Value = e.ProgressPercentage;
        }
    
        private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            progressWindow.Close();
    
            WindowMsgGenDB msg = new WindowMsgGenDB();
            msg.Show();
        }
    }
    

    请注意,上面的代码会进入您的主窗口! MessageWithProgressWindow不包含任何代码。也许Window_Loaded事件处理程序不是启动后台工作程序的正确位置,但是您可以了解它。