2010-07-14 77 views
0

我的backgroundWorker使用ReportProgress來更新ProgressPercentage一個漫長的過程。會發生什麼是在三個項目中的兩個入ProgressChangedProgressPercentage爲零,而每ProgressChangedProgressPercentage的第三個條目是我所期望的。這發生像發條一樣;這是非常可重複的。下面是一些簡單的代碼演示我的設置(減少長度,我已經刪除了錯誤處理代碼):C#BackgroundWorker ReportProgress奇怪行爲

AutoResetEvent areProgressChanged = new AutoResetEvent(false); 

    private void backgroundWorkerProgram_DoWork(object sender, DoWorkEventArgs e) 
    { 
    bool bRetVal = true; 
    int iRetries = 3; 
    int iProgress = 0; 

    // Repeat Program message and entire sequence until programming 
    // is complete or Retries reaches 0... 
    do 
    { 
     bRetVal = Program(); 

     this.eBgwProgramStatus = BgwProgramStatus.BUSY; 
     bRetVal = this.WaitForReceive(SHORT_ACK_WAIT, backgroundWorkerProgram); 

     switch (this.eCommsRsp) 
     { 
      case CommsRsp.ACK: 
       this.eBgwProgramStatus = BgwProgramStatus.BUSY; 
       iRetries = 3; 
       break; 
     } 
    } 
    while ((!backgroundWorkerProgram.CancellationPending) 
     && (!bRetVal) && (iRetries > 0)); 

    // Repeat Write and Data message until programming is complete... 
    do 
    { 
     this.eBgwProgramStatus = BgwProgramStatus.BUSY; 
     bRetVal = Write(); 

     this.eBgwProgramStatus = BgwProgramStatus.BUSY; 
     bRetVal = this.WaitForReceive(SHORT_ACK_WAIT, backgroundWorkerProgram); 

     switch (this.eCommsRsp) 
     { 
      case CommsRsp.ACK: 
       this.eBgwProgramStatus = BgwProgramStatus.BUSY; 
       bRetVal = SendData(pData_c); 
       break; 

      default: 
      case CommsRsp.NACK: 
      case CommsRsp.NONE: 
       this.eBgwProgramStatus = BgwProgramStatus.NO_ACK_RXD; 
       iRetries--; 
       bRetVal = false; 
       break; 
     } 

     this.eBgwProgramStatus = BgwProgramStatus.BUSY; 
     bRetVal = this.WaitForReceive(SHORT_ACK_WAIT, backgroundWorkerProgram); 

     switch (this.eCommsRsp) 
     { 
      case CommsRsp.ACK: 
       this.eBgwProgramStatus = BgwProgramStatus.BUSY; 
       iProgress = (this.iProgramSize * 100)/PIC32.ProgMem.Length; 
       this.backgroundWorkerProgram.ReportProgress(iProgress); 
       this.areProgressChanged.WaitOne(); 
       iRetries = 3; 
       this.iRow++; 
       break; 

      default: 
      case CommsRsp.NACK: 
      case CommsRsp.NONE: 
       this.eBgwProgramStatus = BgwProgramStatus.NO_ACK_RXD; 
       iRetries--; 
       bRetVal = false; 
       break; 
     } 
    } 
    while ((!backgroundWorkerProgram.CancellationPending) 
     && (iRetries > 0) 
     && ((!bRetVal) || (this.eBgwProgramStatus == BgwProgramStatus.BUSY))); 
    } 

    private void backgroundWorkerProgram_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
    string sProgressPercentage = e.ProgressPercentage.ToString() + "%"; 

    // Report progress. 
    this.labelPercentComplete.Visible = true; 
    this.labelPercentComplete.Text = sProgressPercentage; 
    this.toolStripStatusLabel.Text = this.sProgramming + sProgressPercentage; 
    this.textBoxData.AppendText(this.tBusText.ToString()); 
    this.textBoxStatus.AppendText(this.tStatusText.ToString()); 
    this.tBusText.Remove(0, this.tBusText.Length); 
    this.tStatusText.Remove(0, this.tStatusText.Length); 
    this.areProgressChanged.Set(); 
    } 

(對於長度我的道歉,但被要求)。同樣的行爲exhibitted有和沒有AutoResetEvent。有沒有人有任何想法,爲什麼這可能會發生?謝謝。

額外的細節

如果我設置一個斷點上this.backgroundWorkerProgram.ReportProgress(iProgress);,我可以看到iProgress增量預期(慢慢地,在幾個因特瓦勒,如0,0,0,1,1,1,2, 2,2,3,3,3-,等)。然後,如果我將breakpoin移動到string sProgressPercentage = e.ProgressPercentage.ToString() + "%";,則e.ProgressPercentage的值與傳遞的值iProgress不匹配。我得到的就像0,0,0,0,1,0,0,2,0,0,3,0,0等。

+4

而不是僞代碼,爲什麼不給我們一個簡短而完整的例子來說明問題?這會讓你更容易幫助你。 – 2010-07-14 16:19:31

+0

這不是Bgw的正常行爲,所以在你的(真實)代碼中必須有東西引起它。所以我同意Jon的觀點:發佈一個小型演示程序。很可能你會發現一路上的問題。 – 2010-07-14 16:35:34

+0

你有沒有在調試器中通過這段代碼?看起來你只是在非常特定的條件下調用ReportProgress。此外,您傳遞給此方法的值('iProgress')是計算的結果:'(this.iProgramSize * 100)/ PIC32.ProgMem.Length',無論如何。我不清楚,作爲一個外人,你會如何確信這個價值有時不會是零。 – 2010-07-14 16:43:18

回答

0

顯然,在優化應用程序的可伸縮性時引入了這個問題。我終於把程序再次提升到了「穩定」的位置,重新測試了一次,問題就像它出現的神祕一樣消失了。

1

iProgramSize和PIC32.ProgMem.Length的前幾個值是什麼?

例如,如果PIC32.ProgramMem.Length爲300,iProgramSize爲1,2,3,4,5,6等,則完成百分比應爲0,0,1,1,1,2等。

此外,您確定ProgressPercentage傳遞不正確,可能是標籤控件不能正確更新/刷新?

+0

'iProgramSize'從0開始,並遞增到'PIC32.ProgramMem.Length',這是在這部分約512K的應用程序中的一個固定值。 如果我在'this.backgroundWorkerProgram.ReportProgress(iProgress);'上設置了一個斷點,我可以看到'iProgress'按預期遞增(緩慢地在幾個間隔上,例如0,0,0,1,1,1,2 ,2,2,3,3,3-,等)。然後,如果我將breakpoin移動到'string sProgressPercentage = e.ProgressPercentage.ToString()+「%」;',則「e.ProgressPercentage」的值與「iProgress」的傳遞值不匹配。我得到的就像0,0,0,0,1,0,0,2,0,0,3,0,0等。 – 2010-07-14 18:57:31

+0

奇怪。我假設e。ProgressPercentage以值98,0,0,99,0,0,100結尾,假設e.ProgressPercentage爲零時,解決方法是不更新標籤。 與重複輸入數量相關的不正確值(零)的數量,即如果將iProgress更改爲=(this.iProgramSize * 50)/ PIC32.ProgMem.Length,這是否意味着您最終會得到更多的零正確的值之間? – sgmoore 2010-07-14 19:57:15

+0

顯然,這個問題是在優化應用程序可伸縮性時引入的。我終於把程序再次提升到了「穩定」的位置,重新測試了一次,問題就像它出現的神祕一樣消失了。我已經投票贊成你的迴應,因爲你給我的詢問一些批判性的想法,試圖幫助,而不是隻是解僱它。獎勵! – 2010-07-19 21:05:29