2011-12-27 37 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循環完成,而不是之前/在for循環中,即使我在循環之前調用了fillbar()。

Thread方法:

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? WPF? Silverlight的? (etc) – 2011-12-27 16:50:16

+0

@ Muad'Dib從'Timer'類型和'Click'處理程序簽名來看,它是WinForms。 – 2011-12-27 16:59:13

+0

使用BackGroundWorker,就是這麼做的。 – TheBoyan 2011-12-27 17:00:00

回答

6

你做了錯誤的方式。主線程負責更新用戶界面。所以如果你用計算來阻止它,它將無法繪製進度條。將您的計算代碼移到另一個線程中,它應該沒問題。

+1

我將計算代碼移動到了一個新的線程中,就像您建議的那樣,並在主線程中調用了fillbar(),它的工作原理非常感謝!出於好奇心,我嘗試爲fillbar()創建一個新線程(就像問題中那樣),但是這不起作用,爲什麼?也許是因爲eventHandler沒有被添加到新線程?再次感謝 :) – Matt 2011-12-27 16:59:18

1

總是管理用戶界面的主要線程。爲此目的使用backgroundworker。 在Backgroundworker中啓用進度功能將WorkerReportProgress(property)設置爲true,並且 設置WorkerSupportCancellation用於在需要時停止backgroundworker。

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