在处理文件时更新进度条

本文关键字:更新 处理 文件 | 更新日期: 2023-09-27 18:17:26

我有一个有趣的项目,我目前正在工作。这是一个c# WinForms项目。基本上,使用应该加载一个Visual Studio解决方案文件,然后应用程序解析它:根据文件中编写的内容构建对象等等(详细解释它的功能与问题无关,因此我将在此停止)。

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

我的代码是:
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;
    }
}

在处理文件时更新进度条

通常,要显示进度如何变化,您需要在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设置为"选框";在启动线程之前显示它,并将其隐藏在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);
    ...
}