无法使用 BackgroundWorker c#.net 窗体更新单独窗体中的进度条



我是C#.NET的新手。我尝试从主 UI 创建一个带有进度栏的表单以显示进度。我使用BackgroundWorker 来调用它。我可以显示进度对话框,但不能更新进度条值。请在下面找到代码。

主界面 :

namespace GC
{
    public partial class MainUI : Form
    {
        private ProgressBar oProgressBar;
        public MainUI()
        {
            InitializeComponent();
        }
        private void runButton_Click(object sender, EventArgs e)
        {
            oProgressBar = new ProgressBar();
            backgroundWorker1 = new BackgroundWorker();
            backgroundWorker1.WorkerReportsProgress = true;
            backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
            backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
            backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
            backgroundWorker1.RunWorkerAsync();
            oProgressBar.ShowDialog();

        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            //some work here
            for (int i = 0; i < 20; i++)
                backgroundWorker1.ReportProgress(i);

        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            oProgressBar.Close();
        }
        void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            oProgressBar.progressBar1.Value = e.ProgressPercentage;
        }
    }
}

进度栏 UI 此窗体包含一个进度条

namespace GC
{
    public partial class ProgressBar : Form
    {
        public ProgressBar()
        {
            InitializeComponent();
        }

      }
}

根据您提供的信息,有几件事可能是问题所在,但这取决于您遇到的行为:

方案 1:进度栏窗体在看到任何更新之前关闭

问题是您在进度条更新后几乎立即关闭表单。这将发生得如此之快,以至于您将没有时间看到进度条更新。

方案 2:进度栏窗体保持打开状态,并且栏永远不会更新

这对我来说表明您的"Do Work"代码中存在错误,该错误阻止了ReportProgress函数被调用。为了检查这一点,我建议使用调试器逐步执行代码。


你应该做什么

如果毫无意义,则像示例中一样更新 for 循环中的进度条。您的示例将导致进度条立即跳转到 20% 并保持在那里。您应该在执行工作过程的每个"步骤"之后递增进度条。此外,重要的是,您的任务实际上需要一些时间来执行(alteast 一秒钟(,以便有时间显示某些内容。

例如,如果您的任务是从数据库中读取记录,那么例如,您可以在读取每一行后报告进度。我还建议您将其全部包装在 try catch 中并提醒任何错误(只是为了知道,以便您可以调试您的问题(......

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    try
    {
        //Do Stuff: e.g. read from DB
        var tasks = GetTasks();
        int i = 0;
        double percentageIncrease = 100d / tasks.Count();
        foreach(var task in tasks)
        {
            //do something for this task
            backgroundWorker1.ReportProgress((int)(percentageIncrease * i));
            i++;
        }
    }
    catch(Exception ex)
    {
        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK);
    }
}
对我来说

看起来不错,

我认为你的问题更像是:

  • 窗口在您看到它填满之前关闭,因为:

    o进度条.关闭((;

  • 正如 musefan 所说,您的酒吧只填满了 20%,这是正常的,因为:

    for (int i = 0; i <20; i++( 背景工人1.报告进度(i(;

如果你想看到它完全填充,请使用 for 循环到 100:for (int i = 0; i <100; i++(

您需要在

表单线程上调用更新吗?

void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    if(InvokeRequired)
    { 
        Invoke(new EventHandler<ProgressChangedEvent>(backgroundWorker1_ProgressChanged), sender, e);
    }
    else 
        oProgressBar.progressBar1.Value = e.ProgressPercentage;
}

相关内容

最新更新