【问题标题】:Update a progressbar while processing a file处理文件时更新进度条
【发布时间】:2014-08-11 18:20:10
【问题描述】:

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

我有一个主窗体 (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;
    }
}

【问题讨论】:

  • 视情况而定——你的意思是仅仅读取文件还是解析一些文本?
  • 解析。我使用 Regex 和诸如此类的东西来查找一些关键字并将加载文件中的信息加载到我制作的一些类中。
  • 是的,我就是这么做的——谢谢。不过还是没有回答我的问题。
  • 这个方法 openSolution.AnalyzeSolution();需要进入 DoWork 方法开始。但更重要的是,在您的 AnalyzeSolution() 中,您需要继续在您的工作人员上调用 ReportProgress 以便触发事件。把它放在你正在解析文件的循环中。
  • 对,我就是这么想的。但是没有一个解析循环:它调用一堆创建对象、对象列表等的方法(它们调用其他方法)——它不仅仅是一个简单的循环。还有其他方法吗?

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


【解决方案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);
}

由于您没有要迭代的内容,而只想在单独的后台线程中调用您的单个方法,因此不必费心报告进度。除非您以某种方式分解单个方法调用,否则您无能为力。

添加ProgressBar,将Style 设置为“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);

    ...
}

【讨论】:

  • 另外,AnalyzeSolution() 只是连续调用一些(比如说,5 个)其他方法。当每个方法完成时,我可以做一些事情,比如在进度条上增加 20% 吗?我对所有这些事件感到有点困惑。
  • 优秀。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-24
  • 1970-01-01
相关资源
最近更新 更多