Обновите индикатор выполнения при обработке файла

У меня есть веселый проект, над которым я сейчас работаю. Это проект 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;
    }
}

1 ответ

Решение

Обычно, чтобы показать, как меняется прогресс, вам нужно иметь какой-то цикл в вашем DoWork событие, а затем процент и / или сообщение обратно в поток пользовательского интерфейса:

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);

    ...
}
Другие вопросы по тегам