C# BackgroundWorker ReportProgress Behaving Strangely
My backgroundWorker
uses ReportProgress
to update the ProgressPercentage
of a long process. What happens is in two out of three entries into ProgressChanged
ProgressPercentage
is zero, whereas every third entry into ProgressChanged
the ProgressPercentage
is what I would expect. This happens like clockwork; it is very repeatable. Here is some simplified code demonstrating my setup (to reduce the length, I've removed the error-handling code):开发者_StackOverflow社区
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();
}
(My apologies for the length, but it was requested.) The same behavior is exhibitted with and without the AutoResetEvent
. Does anyone have any thoughts as to why this may be happenning? Thanks.
ADDITIONAL DETAILS
If I set a breakpoint on this.backgroundWorkerProgram.ReportProgress(iProgress);
, I can see that iProgress
increments as expected (slowly, over several intervale, e.g. 0,0,0,1,1,1,2,2,2,3,3,3,etc.). Then, if I move the breakpoin to string sProgressPercentage = e.ProgressPercentage.ToString() + "%";
, the value of e.ProgressPercentage
does not match the passed value of iProgress
. What I get is like 0,0,0,0,1,0,0,2,0,0,3,0,0,etc.
What are the first few values of iProgramSize and PIC32.ProgMem.Length ?
For example if PIC32.ProgramMem.Length was 300, and iProgramSize was 1,2,3,4,5,6 etc, then the percentages complete should be 0,0,1,1,1,2 etc.
Also, are you sure the ProgressPercentage is passed incorrectly, could be it that the label control not be updated/refreshed correctly?
Apparently, this problem was somehow introduced while optimizing the application for scalability. I finally got the program to a "stable" point again, retested, and the problem has gone away just as mysteriously as it appeared.
精彩评论