繁体   English   中英

C#Winform ProgressBar和BackgroundWorker

[英]C# Winform ProgressBar and BackgroundWorker

我有以下问题:

我有一个名为MainForm的表单。 我在这张表格上进行了长时间的操作。

虽然这个长时间的操作正在进行,但我需要在MainForm之上显示另一个名为ProgressForm的操作。

ProgressForm包含一个进度条,需要在长时间操作时进行更新。

长操作完成后,应自动关闭ProgressForm。

我写了以下代码:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace ClassLibrary
{
    public class MyClass
    {
        public static string LongOperation()
        {
            Thread.Sleep(new TimeSpan(0,0,30));

            return "HelloWorld";
        }
    }
}

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

namespace BackgroungWorker__HelloWorld
{
    public partial class ProgressForm : Form
    {
        public ProgressForm()
        {
            InitializeComponent();
        }

        public ProgressBar ProgressBar
        {
            get { return this.progressBar1; }
            set { this.progressBar1 = value; }
        }
    }
}

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

using ClassLibrary;

namespace BackgroungWorker__HelloWorld
{
    public partial class MainForm : Form
    {
        ProgressForm f = new ProgressForm();

        public MainForm()
        {
            InitializeComponent();  
        }

        int count = 0;
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (f != null)
            {
                f.ProgressBar.Value = e.ProgressPercentage;
            }

            ++count;
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled) 
            {  
                MessageBox.Show("The task has been cancelled");  
            }  
            else if (e.Error != null)  
            {                  
                MessageBox.Show("Error. Details: " + (e.Error as Exception).ToString());  
            }  
            else 
            {  
                MessageBox.Show("The task has been completed. Results: " + e.Result.ToString());  
            }
        }


        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            if (f == null)
            {
                f = new ProgressForm();
            }

            f.ShowDialog();

            //backgroundWorker1.ReportProgress(100);

            MyClass.LongOperation();

            f.Close();
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            backgroundWorker1.RunWorkerAsync();
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            backgroundWorker1.CancelAsync();

            this.Close();
        }
    }
}

我找不到更新progressBar

我应该在哪里放置backgroundWorker1.ReportProgress()以及如何调用它?

我不能在MyClass做任何更改,因为我不知道在我的应用程序的这一层中完成操作会发生什么或需要多长时间。

谁能帮我?

一个问题是你睡了30秒。 通常,您可以在长时间运行的任务中的不同位置调用ReportProgress 因此,为了证明这一点,您可能希望将代码更改为休眠1秒,但需要30次 - 每次完成睡眠时调用ReportProgress

另一个问题是你后台线程中显示你的ProgressForm 您应该在UI线程中启动它,但是将后台worker的ProgressChanged事件挂钩到它。 然后,当后台工作人员报告进度时,将更新进度表单。

ReportProgress是您必须在“工作”方法中调用的方法。 此方法将引发“ProgressChanged”事件。

在表单中,您可以将事件处理程序附加到ProgressChanged事件。 在事件处理程序内部,您可以更改进度条的位置。 您还可以将事件处理程序附加到RunWorkerCompleted事件,并在该事件处理程序内部,您可以关闭包含进度条的表单。

应该注意你需要设置

backgroundWorker1.WorkerReportsProgress = true;

如果你想让后台工作者提升ProgressChanged事件和

backgroundWorker1.WorkerSupportsCancellation = true;

如果您希望能够取消工作线程。

正如其他人所说,在UI线程中运行f.ShowDialog()并使用ProgressChanged更新ProgressWindow。

要使ProgressForm自行关闭,请在backgroundWorker1_RunWorkerCompleted中调用f.Close(); 这意味着长操作已经完成,我们可以关闭窗口。

这里需要的是不将整个主窗体传递给类,而只是将BackgroundWorker的实例传递给它! 你需要将发送者强制转换为后台工作者,如下所示:

private void bgWorker_DoWork(object sender DoWorkEventArgs e)
{
    // Get the BackgroundWorker that raised this event
    BackgroundWorker worker = sender as BackgroundWorker;

    // And now you just send worker to whatever class you need like so:
    bgArgs args = e.Argument as bgArgs;
    MyClass objMyClass = new MyClass();

    MyClass.MyMethod(strValue, args.Option, worker);

    // Do something based on return value.
}

然后在你的MyClass.MyMethod()你将进行进度计算并简单地引发worker.ReportProgress(int percentage)事件来更新主UI表单上的进度条或诸如此类的东西!

这应该完美!

查看这篇MSDN文章了解更多详细信息,请参阅他们的Fibonacci示例,这是他们的工作,因为CalculateFibonacci是一个自定义类,它向主窗体的UI发送更新。

有关更多详细信息,请参阅MSDN BackgroundWorker类

暂无
暂无

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

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