Backgroundworker ProgressChanged在工作完成后执行

时间:2012-07-30 22:02:55

标签: c# winforms backgroundworker multithreading

我创建了一个表单,只要我调用一个耗时的例程,就会弹出并显示一个进度条。我通过UpdateProgress方法提供了例程的进度。

我正在使用后台工作程序,允许用户在此表单更新时移动表单并继续开展业务。但是,表单只是锁定直到例程完成,然后快速将进度条斜坡上升到100%并退出(应该如此)。进度条应该imo随着对UpdateProgress方法的调用进度而更新。

我在这里做错了什么?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace myNameSpace
{
    public partial class ProgressIndicator : Form
    {
        int progressPercentage;

        public ProgressIndicator()
        {
            InitializeComponent();
        }

        void progressUpdater_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            // update the UI with appropriate fields
            progressBar.Value = e.ProgressPercentage;
            labelCommunicating.Text = "In progress: " + e.ProgressPercentage + "% complete";
        }

        void progressUpdater_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.Close();
        }

        void progressUpdater_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            while (true)
            {
                if (progressPercentage >= 100)
                {
                    break;
                }

                worker.ReportProgress(progressPercentage);

                Thread.Sleep(100);
            }
        }

        public void UpdateProgress(int progressPercentage)
        {
            this.progressPercentage = progressPercentage;
        }

        private void ProgressIndicator_Load(object sender, EventArgs e)
        {
            BackgroundWorker progressUpdater = new BackgroundWorker();
            progressUpdater.WorkerReportsProgress = true;
            progressUpdater.WorkerSupportsCancellation = true;
            progressUpdater.DoWork += new DoWorkEventHandler(progressUpdater_DoWork);
            progressUpdater.RunWorkerCompleted += new RunWorkerCompletedEventHandler(progressUpdater_RunWorkerCompleted);
            progressUpdater.ProgressChanged += new ProgressChangedEventHandler(progressUpdater_ProgressChanged);

            progressUpdater.RunWorkerAsync();
        }
    }
}

2 个答案:

答案 0 :(得分:1)

这闻起来像一个牵强附会的解决方案,我认为你的问题在于while loop。但是,更好的方法可能是使用ProgressBar简单地更新Invoke();而不阻止用户界面,例如

Invoke(new myUpdate(updateProgress), pval);//call invoke whenever you need to update the progress bar assuming pval is an integer with the value to update with. This could be in a thread for instance.

//declare this as a class level delegate
private delegate void myUpdate(int progress);

//method to update progress bar
private void updateProgress(int progress)
{
    progressBar.Value = progress;
}

答案 1 :(得分:0)

您可以这种方式创建流程,这样您就不需要围绕Invoke方法打包调用。

//delegate method
private delegate void updateProgressDelegate(int progress);

//actual method
private void updateProgress(int progress)
{
    if(this.InvokeRequired)
    {
        this.Invoke(new updateProgressDelegate(updateProgress), progress);
    }
    else
    {
        progressBar.value = progress;
    }
}