Originally Posted by
Alex F
How progress information is sent to the main thread?
Like that:
Code:
System::Void Form1::DoCountWorker(FileStream ^fsInfile,BackgroundWorker ^bw,DoWorkEventArgs ^e)
{
BinaryReader brInfile(fsInfile);
const int nBufferSize=512;
array<Byte> ^abBuffer;
int nPercent=0,nLastPercent=-1;
do {
abBuffer=brInfile.ReadBytes(nBufferSize);
for (int i=0;i<abBuffer->Length;++i)
++aulCounts[abBuffer[i]];
if ((nPercent=(100*fsInfile->Position)/fsInfile->Length)!=nLastPercent) {
bw->ReportProgress(nPercent);
nLastPercent=nPercent;
}
} while (!bw->CancellationPending && abBuffer->Length==nBufferSize);
brInfile.Close();
if (bw->CancellationPending) e->Cancel=true;
}
System::Void Form1::bwDoCount_ProgressChanged(System::Object^ sender, System::ComponentModel::ProgressChangedEventArgs^ e)
{
progress->Text=String::Format("Processing file... {0}%",e->ProgressPercentage);
progress->progressBar1->Value=e->ProgressPercentage;
}
Where progress is the progress dialog form object.
By debugging I found out that the bwDoCount_ProgressChanged() event handler runs in the context of the GUI thread, so IMO inter-thread communication is done internally by BackgroundWorker.
But the progress display doesn't cause the deadlock anyway, the problem was only exposed when I clicked the Cancel button. Cancellation is handled by this simple event handler in the progress dialog's form class:
Code:
System::Void Progress::bnCancel_Click(System::Object^ sender, System::EventArgs^ e)
{
bwParentWorker->CancelAsync();
}
Where bwParentWorker is a tracking handle to the BackgroundWorker object that gets passed (i.e. assigned) from the main form object to the progress dialog's form object.
Closing the progress dialog in case I did not click the cancel button is donne by the completion handler (and works):
Code:
System::Void Form1::bwDoCount_RunWorkerCompleted(System::Object^ sender, System::ComponentModel::RunWorkerCompletedEventArgs^ e)
{
if (e->Error) MessageBox::Show(this,e->Error->Message,"Error during file processing",MessageBoxButtons::OK,MessageBoxIcon::Error);
bCountCancelled=e->Cancelled;
if (progress->Visible) progress->Close(); // Progress dialog is still open: close it
Cursor->Current=csrSaved; // This has just been added in response to Arjay's latest post
ewhWorkerReallyFinished->Set();
}
But, as described above, this handler doesn't even get called when I click Cancel.