2011-12-27 2 views
2

У меня есть индикатор выполнения и хочу заполнить его с помощью отдельного потока, потому что основной поток задерживается на несколько секунд в цикле. Я использую таймер так, чтобы индикатор выполнения заполнился в течение определенного промежутка времени.C# Заполнение индикатора выполнения в отдельной строке

создание Тема:

private void PlayButton_Click(object sender, EventArgs e) 
     { 
      progressBar1.Value = 0; 
      int playTime = getPlayTime(); 
      int progressInterval = playTime/100; 
      Thread progressThread = new Thread(barfiller=>fillBar(progressInterval)); 
      progressThread.Start(); 

      //Loops through the collection and plays each note one after the other 
      foreach (MusicNote music in this.staff.Notes) 
      { 
       music.Play(music.Dur); 
       Thread.Sleep(music.getInterval(music.Dur)); 
      } 
      progressThread.Abort(); 
     } 

как есть, ничего не происходит с индикатором прогресса, однако если я называю fillbar() в основном потоке, он работает, но он заполняет после того, как цикл завершен, и не раньше/во время цикла for, хотя я вызываю fillbar() перед циклом.

методы Тема:

private void fillBar(int progressInterval) 
     { 
      progressTimer = new System.Windows.Forms.Timer(); 
      progressTimer.Tick += new EventHandler(clockTick); 
      progressTimer.Interval = progressInterval; //How fast every percentage point of completion needs to be added 
      progressTimer.Start(); 

     } 

     public void clockTick(object sender, EventArgs e) 
     { 
      if (progressBar1.Value < 100) 
      { 
       progressBar1.Value++; 
      } 
      else 
      { 
       progressTimer.Stop(); 
      } 

     } 
+1

winforms? МОФ? Silverlight? (и т. д.) –

+0

@ Muad'Dib Судя по типу 'Timer' и' Click', это WinForms. –

+0

Используйте BackGroundWorker, вот для чего это. – TheBoyan

ответ

6

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

+1

Я переместил вычислительный код в новый поток, как вы предложили, и назвал fillbar() в основном потоке, и это сработало, спасибо большое! Из любопытства я попытался создать новый поток для fillbar() (как в вопросе), но это не сработало, какие-либо идеи относительно чего? Может быть, потому, что eventHandler не был добавлен в новый поток? Еще раз спасибо :) – Matt

1

всегда основной поток для управления пользовательским интерфейсом. используйте backgroundworker для этой цели. , чтобы включить функцию прогресса в наборе фоновых рисунков WorkerReportProgress (свойство) в true и set WorkerSupportCancellation для остановки фонового рабочего при необходимости.

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 
     // also use sender as backgroundworker 
     int i = 0; 
     foreach (MusicNote music in this.staff.Notes) 
     { 
      if(backgroundWorker1.CancellationPending) return; 
      music.Play(music.Dur); 
      Thread.Sleep(music.getInterval(music.Dur)); 

      int p = (int) (i*100/ staff.Notes.Count); /*Count or Length */ 
      backgroundWorker1.ReportProgress(p); 
      i++; 
     } 
     backgroundWorker1.ReportProgress(100); 
    } 

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     progressBar1.Value = e.ProgressPercentage; 
    } 
Смежные вопросы