2010-07-14 78 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