【发布时间】:2010-07-14 16:15:24
【问题描述】:
我的backgroundWorker使用ReportProgress更新了一个漫长的过程的ProgressPercentage。在ProgressChanged ProgressPercentage 的三个条目中有两个是零,而ProgressChanged 的每三个条目ProgressPercentage 是我所期望的。这就像发条一样发生;这是非常可重复的。下面是一些演示我的设置的简化代码(为了减少长度,我删除了错误处理代码):
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();
}
(我为长度道歉,但有人要求。)无论有没有AutoResetEvent,都会表现出相同的行为。有没有人对为什么会发生这种情况有任何想法?谢谢。
附加细节
如果我在this.backgroundWorkerProgram.ReportProgress(iProgress); 上设置断点,我可以看到iProgress 按预期递增(慢慢地,在几个间隔内,例如 0,0,0,1,1,1,2,2,2,3 ,3,3 等)。然后,如果我将断点移动到string sProgressPercentage = e.ProgressPercentage.ToString() + "%";,e.ProgressPercentage 的值与iProgress 的传递值不匹配。我得到的是 0,0,0,0,1,0,0,2,0,0,3,0,0 等。
【问题讨论】:
-
为什么不给我们一个简短而完整的例子来说明问题,而不是伪代码呢?这样可以更轻松地为您提供帮助。
-
这不是 Bgw 的正常行为,因此您的(真实)代码中一定有某些东西导致了它。所以我同意乔恩的观点:发布一个小型演示程序。您很可能会在此过程中发现问题。
-
您是否在调试器中单步执行过这段代码?看起来您只是在非常特定的条件下才调用
ReportProgress。此外,您传递给此方法的值 (iProgress) 是计算的结果:(this.iProgramSize * 100) / PIC32.ProgMem.Length,不管它是什么。作为一个局外人,我不清楚是什么让你如此确定这个值有时不会为零。 -
PIC32.ProgMem.Length是应用程序此时的固定值;也就是说,它只能通过用户干预来更改,并且在此代码运行时相关的用户控件被禁用。随着序列的进行,iProgramSize从零递增到PIC32.ProgMem.Length。我正在考虑使用全局变量进行快速修复。我知道,它不漂亮,但这是更重要的事情。
标签: c# backgroundworker