2015-02-11 3 views
0

Я использую C# с WinForms. Я обновляю progressBar. Когда значение достигает максимального значения, я бы хотел, чтобы он отображал messageBox.Как определить, когда будет выполнен прогресс?

В любом случае для progressBar необходимо выполнить метод, когда он будет заполнен? Так, то некоторые образцы кода или ссылка на решение будут оценены

private void BackgroundWorkerProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     //throw new NotImplementedException(); 
    } 

    private void bgWorker_DoWork(object sender, DoWorkEventArgs e) 
    { 


    } 

    // Back on the 'UI' thread so we can update the progress bar - and our label :) 
    void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     // The progress percentage is a property of e 
     int percentComplete = progressBarStatus.Value/progressBarStatus.Maximum; 
     labelPercentComplete.Text = percentComplete.ToString() + "% Completed"; 

     //progressBarStatus.Value = e.ProgressPercentage; 
     //labelPercentComplete.Text = String.Format("Trade{0}", e.ProgressPercentage); 
    } 

    private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     if(progressBarStatus.Value == progressBarStatus.Maximum) 
     { 
      MessageBox.Show("Test"); 
     } 
    } 


public void Form1_Load(object sender, EventArgs e) 
{ 

backgroundWorker1.DoWork += new DoWorkEventHandler(bgWorker_DoWork); 
      backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler 
          (bgWorker_RunWorkerCompleted); 
      backgroundWorker1.ProgressChanged += BackgroundWorkerProgressChanged; 
} 
+6

Звучит так, что индикатор прогресса не находится под вашим контролем. Поскольку вы обновляете его значение, вы можете проверить, является ли это значение максимальным при обновлении, и соответственно отображать окно сообщения. –

+0

Значение progressBar обновляется из другой формы. Итак, как бы я проверил (без постоянного опроса progressBar), чтобы получить значение? Логика не сложна, если (progressBar1.Value == progressBar1.Maximum) {// что-то делать} –

+2

Кажется, что архитектура нуждается в переосмыслении немного, и, возможно, другая форма должна поднимать некоторые события, которые вы можете слушать. Или без этого рефакторинга и для того, чтобы он был похож на то, как он сейчас, поместите функцию в свою форму шага прогресса, которая может быть вызвана из другой формы, когда это необходимо –

ответ

3

Похоже, что вы не хотите что-то делать, когда работник фона завершается, но вы хотите что-то сделать, когда индикатор выполнения достигнет максимума ... Хорошо, сначала установите максимальное значение progressBarStatus, тогда вы должны попробовать что-то вроде этого :

void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     if (progressBarStatus.Maximum == e.ProgressPercentage) 
     { 
      // do whatever you want to do 
     } 
    } 

и обновить progressBarStatus значение из другой формы. Altough это не может лучший способ делать вещи, если это действительно то, что вы хотите, а затем делать все, что делает вас счастливым ... :)

EDIT: Хорошо, я добавил полный пример программы, которая работает отлично , с вызовом события ProgressChanged и правильной проверкой максимального значения, когда достигнуто максимальное значение, ProgressBar перезапускается и сообщение печатается в окне «Выход» с кучей комментариев (и кучей опечаток курса: D), попробуйте этот пример, посмотрите, как он работает, и примените его к вашей проблеме.

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

namespace BGWORKERAPP 
{ 
    public partial class Form1 : Form 
    { 

     BackgroundWorker bgWorker = new BackgroundWorker(); 
     public Form1() 
     { 
      InitializeComponent(); 
      bgWorker.DoWork += bw_DoWork; 
      bgWorker.WorkerReportsProgress = true;  // needed to be able to report progress 
      bgWorker.WorkerSupportsCancellation = true; // needed to be able to stop the thread using CancelAsync(); 
      bgWorker.ProgressChanged += bw_ProgressChanged; 
      bgWorker.RunWorkerCompleted += bw_RunWorkerCompleted; 

      // ProgressBar is added to the form manually, and here I am just setting some initial values 
      progressBarStatus.Maximum = 100; 
      progressBarStatus.Minimum = 0; 
      progressBarStatus.Value = 0; 
      progressBarStatus.Step = 10; 
     } 
     void bw_DoWork(object sender, DoWorkEventArgs e) 
     { 
      int i = 0; 
      while (true) // keep looping until user presses the "Stop" button 
      { 
       if (bgWorker.CancellationPending) // if bgWorker.CancelAsync() is called, this CancelationPending token will be set, 
       {         // and if statement will be true 
        bgWorker.CancelAsync(); 
        return;  // Thread is getting canceled, RunWorkerCompleted will be called next 
       } 

       i++; // add any value you want, I chose this value because of the test example... 
       Thread.Sleep(1); // give thread some time to report (1ms is enough for this example) - NECESSARY, 
            //WITHOUT THIS LINE, THE MAIN THREAD WILL BE BLOCKED! 
       bgWorker.ReportProgress(i); // report progress (will call bw_ProgressChanged) - NECESSARY TO REPORT PROGRESS! 
      } 
     } 
     int somethingTerrible = 1; // used to do something terrible ;) 
     void bw_ProgressChanged(object sender, ProgressChangedEventArgs e) 
     { 
      // I added this "somethingTerrible" variable to make the ProgressChanged run all over again, even when e.ProgressPercentage value 
      // is greater then the progressBarStatus.Maximum, but, you should call bw.CancelAsync() because the job should be finished. 
      // Also, this code will give you Exception eventually, numbers are limited after all... 
      if (somethingTerrible * progressBarStatus.Maximum == e.ProgressPercentage) 
      { 
       Debug.WriteLine("THIS IS CALLED WHEN THE MAXIMUM IS REACHED"); // this will be printed in the Output window 
       progressBarStatus.Value = 0; // progressBarStatus value is at the maximum, restart it (or Exception will be thrown) 

       //bw.CancelAsync(); // used to stop the thread when e.ProgressPercentage is equal to progressBarMaximum, but in our 
             // example, we just make the code keep running. 
             // We should cancel bgWorker now because the work is completed and e.ProgressPercentage will 
             // be greater then the value of the progressBarStatus.Maximum, but if you really want 
             // you can do something like this to make the thread keep reporting without any errors (until numbers reach the limit)... 
       somethingTerrible++; 
      } 
      else 
      { 
       progressBarStatus.Value++; // increasing progressBarStatus.Value, until we get to the maximum. 
      } 
     } 
     void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      MessageBox.Show("Worker completed"); // worker finished the task... 
     } 

     // Buttons are added to the Form manually as well 
     private void runBgTask_Click(object sender, EventArgs e) // button on the Form to start the thread 
     { 
      bgWorker.RunWorkerAsync(); // start the background worker (call DoWork) 
     } 

     private void stopBgTask_Click(object sender, EventArgs e) // button on the Form to stop the thread 
     { 
      bgWorker.CancelAsync(); // tell the background worker to stop (will NOT stop the thread immediately); the DoWork will be 
            // called once again, but with CancelationPending token set to true, so the if statement 
            // in the DoWork will be true and the thread will stop. 
     } 
    } 
} 
+0

Да, это правильно, но метод не стреляет. Я добавил точку останова и MessageBox.Show(). Я что-то упускаю? –

+0

Да, вам нужно сообщить о прогрессе, используя [bgWorker.ReportProgress (Int32)] (https://msdn.microsoft.com/en-us/library/ka89zff4 (v = vs.110) .aspx), я добавил редактирование , проверьте это ... – miselking

+0

Спасибо за ваш код. Я очень ценю это. Я наблюдаю то, что отличается от того, что я ожидаю. Таким образом, у меня есть form2, который обрабатывает HTML-страницу. Форма 2 невидима и есть 5 шагов. По завершении каждого шага мы сообщаем о прогрессе в Form1. Однако, когда progressBar достигает максимального значения (5), я хочу запустить другой метод, чтобы сделать что-то еще. Пока давайте предположим, что он выдает сообщение с сообщением «Я сделан». –

2

Я думаю, вы должны смотреть на BackgroundWorker, который сделан специально для этой цели. Вы получите Event RunWorkerCompleted, когда ваша работа будет завершена. Я даю вам рабочий пример, в котором вы копируете большое количество файлов.

BackgroundWorker bgWorker = new BackgroundWorker(); 
bgWorker.DoWork += BackgroundWorkerDoWork; 
bgWorker.ProgressChanged += BackgroundWorkerProgressChanged; 
bgWorker.RunWorkerCompleted += new BackgroundWorkerCompletedEventHandler 
       (bgWorker_RunWorkerCompleted); 

void StartWork() 
{ 
// Start BackGround Worker Thread 
    bgWorker.RunWorkerAsync(); 

} 

void BackgroundWorkerDoWork(object sender, DoWorkEventArgs e) 
{ 
    //NOTE : DONT play with the UI thread here... 
    // Do Whatever work you are doing and for which you need to show progress bar 
    CopyLotsOfFiles() // This is the function which is being run in the background 
    e.Result = true;// Tell that you are done 
} 

void CopyLotsOfFiles() 
{ 
    Int32 counter = 0; 
    List<String> filestobeCopiedList = ...; // get List of files to be copied 
    foreach (var file in filestobeCopiedList) 
    { 
     counter++; 
     // Calculate percentage for Progress Bar 
     Int32 percentage = (counter * 100)/filesCount; 
     bgWorker.ReportProgress(percentage); 

     // Files copy code goes here 
    } 
    bgWorker.ReportProgress(100); 
} 

void BackgroundWorkerProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    // Access Main UI Thread here 
    progressBar1.Value = e.ProgressPercentage; 
} 

private void BackgroundWorkerCompletedEventHandler(object sender, RunWorkerCompletedEventArgs e) 
{ 
    //Always check e.Cancelled and e.Error before checking e.Result! 
    //even though I'm skipping that here 
    var operationSuccessFul = Convert.ToBoolean(e.Result); 
    if(operationSuccessFul) 
    MessageBox.Show("I am Done"); 
} 

Вы получите звонок в BackgroundWorkerCompletedEventHandler, когда вы закончите. Вы должны отобразить индикатор выполнения в обработчике событий BackgroundWorkerProgressChanged.

+0

Я видел это, но можете ли вы показать мне, что бы вы добавили в событие RunWorkerCompleted? –

+0

Выполняйте все, что хотите, если вы хотите показать окно сообщения, просто сделайте Messagebox.Show («Готово»); в bgWorker_RunWorkerCompleted обработчик события – Pankaj

+0

Извините, но RunWorkerCompleted будет срабатывать, но когда? Я немного смущен о специфике того, как он будет знать, когда progressBar1.Value является progressBar1.Maximum –

1

Вы должны подумать об обратном: создать центральный «класс прогресса». Этот класс отвечает за:

  1. Обновление строки прогресса
  2. Показывать MessageBox при выполнении определенных условий

Или иначе говоря: сво не responibility от ProgressBar к .. делать что-то еще, кроме как показывать прогресс.

Смежные вопросы