处理文件时更新进度条

时间:2014-08-11 18:20:10

标签: c# user-interface progress-bar backgroundworker

我目前正在开展一个有趣的项目。这是一个C#WinForms项目。基本上,应该使用Visual Studio解决方案文件,然后应用程序解析它:根据文件中的内容构建对象等等(解释它的详细内容与问题无关,所以我&#39 ;停在这里。)

我有一个主窗体(frmMain),它提供了加载文件的界面,还有一个进度条(analyzingProgressBar应该来显示进度文件解析,因为它需要几秒钟。我已经设置了BackgroundWorker,但我被卡住了 - 如何根据实际进度更新prgressbar?

我的代码是:

public partial class frmMain : Form
{
    public frmMain()
    {
        InitializeComponent();
        toolStripPseudo.Text = String.Empty;
        toolStripPseudo.Spring = true;
    }

    private void openSolutionToolStripMenuItem_Click(object sender, EventArgs e)
    {
        if (openSolutionDialog.ShowDialog() == DialogResult.OK)
        {
            Solution openSolution = new Solution(openSolutionDialog.FileName);

            BackgroundWorker worker = new BackgroundWorker();
            worker.WorkerReportsProgress = true;
            worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.RunWorkerCompleted);
            worker.ProgressChanged += new ProgressChangedEventHandler(this.ProgressChanged);
            worker.DoWork += new DoWorkEventHandler(this.DoWork);

            // start the worker thread
            worker.RunWorkerAsync(openSolution);
        }
    }

    private void DoWork(object sender, DoWorkEventArgs e)
    {
        // get a reference to the worker that started this request
        BackgroundWorker workerSender = sender as BackgroundWorker;

        Solution openSolution = e.Argument as Solution;
        openSolution.AnalyzeSolution();

        workerSender.ReportProgress() //What do I do here?
    }

    private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // TODO add graphics
    }

    public void ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        analyzingProgressBar.Value = e.ProgressPercentage;
    }
}

1 个答案:

答案 0 :(得分:1)

通常,要显示进度如何变化,您需要在DoWork事件中进行某种循环,然后将百分比和/或消息返回到UI线程:

private void DoWork(object sender, DoWorkEventArgs e)
{
    var workerSender = (BackgroundWorker)sender;

    // I know I'm making this up.. I have no idea what your method does/returns
    var filesToAnalyze = ((Solution)e.Argument).AnalyzeSolution();

    for (var i = 0; i < filesToAnalyze.Length; i++)
        workerSender.ReportProgress(0, "Analyzing file #" + i);
}

由于您没有任何要迭代的内容,只是想在单独的后台线程中调用您的单个方法,所以不要打扰报告进度。除非你以某种方式打破单一方法调用,否则你无能为力。

添加ProgressBarStyle设为“Marquee”;在启动线程之前显示它并将其隐藏在RunWorkerCompleted事件中:

progressBar.Show();
worker.RunWorkerAsync(openSolution);
...

private void DoWork(object sender, DoWorkEventArgs e)
{
    var openSolution = (Solution)e.Argument;

    // Run long method (which can't touch the UI, or it'll throw an exception)
    openSolution.AnalyzeSolution();
}

private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    progressBar.Hide();  // Hide progress bar when job complete
}

  

AnalyzeSolution()只是连续调用一些(比方说,5)其他方法。我可以在每个方法完成时向进度条添加20%吗?

是的,但是你必须调用这5种方法,而不是只调用AnalyzeSolution()

private void DoWork(object sender, DoWorkEventArgs e)
{
    var workerSender = (BackgroundWorker)sender;
    var openSolution = (Solution)e.Argument;

    openSolution.RunMethodOne();
    workerSender.ReportProgress(20);

    openSolution.RunMethodTwo();
    workerSender.ReportProgress(40);

    ...
}