Problems with BackgroundWorker

  • Thread starter Thread starter Carsten Marx
  • Start date Start date
C

Carsten Marx

Hello,
now i successfully added a BackgroundWorker to my App on a panel with:

BackgroundWorker bgWorker;
.....
.....
this.bgWorker = new BackgroundWorker();
this.bgWorker.DoWork +=new DoWorkEventHandler(bgWorker_DoWork);
this.bgWorker.ProgressChanged +=new
ProgressChangedEventHandler(bgWorker_ProgressChanged);
this.bgWorker.RunWorkerCompleted +=new
RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
this.bgWorker.WorkerReportsProgress = true;
this.bgWorker.WorkerSupportsCancellation = true;
.....
public void sieveIt(int position)
{
....// some computation
this.organizeTheSieveOrder();
this.cleanTheView(); // remove all "old" controls from the panel
this.Controls.Add(this.progressPanel); //add the status panel
this.bgWorker.RunWorkerAsync(this); // start the BackgroundWorker
}
.....

private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
this.actualizeClustersSizes();
/* in actualizeClustersSizes there are opened a few database connections
to get data.. withuot touching the gui... in the method after each
connection there is an this.bgWorker.ReportProgress(v) where v is the
current percentage... */
}

private void bgWorker_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
this.progressLabel.Text = e.ProgressPercentage.ToString() + " %";
this.progressBar.Value = e.ProgressPercentage;
}

private void bgWorker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
this.progressBar.Value = 0;
this.Controls.Remove(this.progressPanel); // remove the progresspanel
this.refreshView(); // refresh the Panel and add the new controls
if(this.currentStep == 3) this.showTable(true);
this.bgWorker.CancelAsync(); // cancel the bgWorker
}


Moe my Problem is, that everything works fine for a while... but when i
work a little bit with the app, the app is freezing.... and it's not
repeatable... Why?
Another question: Is it possible to stop the BgWoker at my own (like:
bgWorker.Stop() ...)

Thanks for any help...

Regards
Carsten
 
Looking at your code there is only one oddity that you should remove. In the
_RunWorkerCompleted method don't call CancelAsync. At that point the BW is
telling you it is finished so there is no point to cancel.
work a little bit with the app, the app is freezing.... and it's not
The only way you'd get a freeze is if you touched the GUI from the_DoWork
method which you claim you don't. Do you use threads anywhere else in the
app?
Another question: Is it possible to stop the bgWoker at my own (like:
It is possible. Doing this requires 3 small modifications in the client
code:
1. In the _DoWork event periodically check for cancelation (e.g. check every
time you report progress like the sample on my blog)
if (bgWorker.CancellationPending == true){
e.Cancel = true;
return;
}

2. Optionally in the _RunWorkerCompleted check that it has been stopped
using the e.Cancelled [in your code it looks like you don't care how the job
completed]

3. From anywhere in your code call bgWoker.CancelAsync

Cheers
Daniel
 
Daniel said:
Looking at your code there is only one oddity that you should remove. In
the _RunWorkerCompleted method don't call CancelAsync. At that point the
BW is telling you it is finished so there is no point to cancel.
work a little bit with the app, the app is freezing.... and it's not

The only way you'd get a freeze is if you touched the GUI from
the_DoWork method which you claim you don't. Do you use threads anywhere
else in the app?
Another question: Is it possible to stop the bgWoker at my own (like:

It is possible. Doing this requires 3 small modifications in the client
code:
1. In the _DoWork event periodically check for cancelation (e.g. check
every time you report progress like the sample on my blog)
if (bgWorker.CancellationPending == true){
e.Cancel = true;
return;
}

2. Optionally in the _RunWorkerCompleted check that it has been stopped
using the e.Cancelled [in your code it looks like you don't care how the
job completed]

3. From anywhere in your code call bgWoker.CancelAsync

Cheers
Daniel
--
http://www.danielmoth.com/Blog/


Hello,
now i successfully added a BackgroundWorker to my App on a panel with:

BackgroundWorker bgWorker;
....
....
this.bgWorker = new BackgroundWorker();
this.bgWorker.DoWork +=new DoWorkEventHandler(bgWorker_DoWork);
this.bgWorker.ProgressChanged +=new
ProgressChangedEventHandler(bgWorker_ProgressChanged);
this.bgWorker.RunWorkerCompleted +=new
RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
this.bgWorker.WorkerReportsProgress = true;
this.bgWorker.WorkerSupportsCancellation = true;
....
public void sieveIt(int position)
{
....// some computation
this.organizeTheSieveOrder();
this.cleanTheView(); // remove all "old" controls from the panel
this.Controls.Add(this.progressPanel); //add the status panel
this.bgWorker.RunWorkerAsync(this); // start the BackgroundWorker
}
....

private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
this.actualizeClustersSizes();
/* in actualizeClustersSizes there are opened a few database
connections to get data.. withuot touching the gui... in the method
after each connection there is an this.bgWorker.ReportProgress(v)
where v is the current percentage... */
}

private void bgWorker_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
this.progressLabel.Text = e.ProgressPercentage.ToString() + " %";
this.progressBar.Value = e.ProgressPercentage;
}

private void bgWorker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
this.progressBar.Value = 0;
this.Controls.Remove(this.progressPanel); // remove the progresspanel
this.refreshView(); // refresh the Panel and add the new controls
if(this.currentStep == 3) this.showTable(true);
this.bgWorker.CancelAsync(); // cancel the bgWorker
}


Moe my Problem is, that everything works fine for a while... but when
i work a little bit with the app, the app is freezing.... and it's not
repeatable... Why?
Another question: Is it possible to stop the BgWoker at my own (like:
bgWorker.Stop() ...)

Thanks for any help...

Regards
Carsten
Thanks for your help... but it' still not working.. i'm frustrated....
Here my methode actualizeClusterSizes, which is processed in the _DoWork :
public void actualizeClustersSizes()
{
this.inProgress = true;
int pos = this.currentStep < this.maxSteps ? this.currentStep : 2;
string category = this.categories[pos][0];
SieveMapCluster[][] clusters = this.cACTIVE;
//connect to the db
DataManager.DB.connect();
//go through the cateory array and get the size of the clusters
int countSteps = 0;
foreach(SieveMapCluster[] cs in clusters)
{
foreach(SieveMapCluster c in cs)
{
countSteps++;
}
}
int countCurrentStep = 0;
foreach(SieveMapCluster[] cs in clusters)
{
foreach(SieveMapCluster c in cs)
{
string cQ = "";
// if no KEYWORDS set the sql is a little bit different..
if(KeywordManager.KEYWORDS.Length == 0)
{
cQ = " WHERE(";
}
else
{
cQ = " AND(";
}
int i=0;
foreach(string s in c.Keywords)
{
cQ += category + " = '" + s + "' ";
if(c.Keywords.Length>1 && i < c.Keywords.Length-1) cQ += " OR ";
i++;
}
countCurrentStep++;
int v =
System.Math.Min(100,(int)(this.progressBar.Maximum*((double)((double)countCurrentStep/(double)countSteps))));
this.bgWorker.ReportProgress(v);
cQ += ")";
DataManager.DB.ClusterQuery = cQ;
string count = "SELECT COUNT(*) FROM main" + DataManager.DB.addQuery();
try
{
c.CSize = DataManager.DB.getClusterSize(count);
}
catch(Exception ae)
{

}
}
}
DataManager.DB.close();
this.inProgress = false;
}

Whats wrong here?
 
this.progressBar.Maximum is a UI element. Do not touch it from that method
and see if the freeze occurs again.

You have two options for substituting it.
a) Hardcode the value or store the value in a form level variable
b) Actually pass it as an argument to BW when you call RunWorkerAsync and
then use the it in DoWork e.g. (int)e.Argument

Regardless of how you remove the above I just noticed another oddity with
your code. You are passing to RunWorkerAsync the form (this). There is no
point in doing so since
a) You are not using it in DoWork
b) You can't use it in DoWork (it is a UI element)

Maybe you meant to pass it to the constructor of BW, which is fine (and in
fact required if you run the same code on the desktop)

Cheers
Daniel
--
http://www.danielmoth.com/Blog/


Carsten Marx said:
Daniel said:
Looking at your code there is only one oddity that you should remove. In
the _RunWorkerCompleted method don't call CancelAsync. At that point the
BW is telling you it is finished so there is no point to cancel.
work a little bit with the app, the app is freezing.... and it's not

The only way you'd get a freeze is if you touched the GUI from the_DoWork
method which you claim you don't. Do you use threads anywhere else in the
app?
Another question: Is it possible to stop the bgWoker at my own (like:

It is possible. Doing this requires 3 small modifications in the client
code:
1. In the _DoWork event periodically check for cancelation (e.g. check
every time you report progress like the sample on my blog)
if (bgWorker.CancellationPending == true){
e.Cancel = true;
return;
}

2. Optionally in the _RunWorkerCompleted check that it has been stopped
using the e.Cancelled [in your code it looks like you don't care how the
job completed]

3. From anywhere in your code call bgWoker.CancelAsync

Cheers
Daniel
--
http://www.danielmoth.com/Blog/


Hello,
now i successfully added a BackgroundWorker to my App on a panel with:

BackgroundWorker bgWorker;
....
....
this.bgWorker = new BackgroundWorker();
this.bgWorker.DoWork +=new DoWorkEventHandler(bgWorker_DoWork);
this.bgWorker.ProgressChanged +=new
ProgressChangedEventHandler(bgWorker_ProgressChanged);
this.bgWorker.RunWorkerCompleted +=new
RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
this.bgWorker.WorkerReportsProgress = true;
this.bgWorker.WorkerSupportsCancellation = true;
....
public void sieveIt(int position)
{
....// some computation
this.organizeTheSieveOrder();
this.cleanTheView(); // remove all "old" controls from the panel
this.Controls.Add(this.progressPanel); //add the status panel
this.bgWorker.RunWorkerAsync(this); // start the BackgroundWorker
}
....

private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
this.actualizeClustersSizes();
/* in actualizeClustersSizes there are opened a few database connections
to get data.. withuot touching the gui... in the method after each
connection there is an this.bgWorker.ReportProgress(v) where v is the
current percentage... */
}

private void bgWorker_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
this.progressLabel.Text = e.ProgressPercentage.ToString() + " %";
this.progressBar.Value = e.ProgressPercentage;
}

private void bgWorker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
this.progressBar.Value = 0;
this.Controls.Remove(this.progressPanel); // remove the progresspanel
this.refreshView(); // refresh the Panel and add the new controls
if(this.currentStep == 3) this.showTable(true);
this.bgWorker.CancelAsync(); // cancel the bgWorker
}


Moe my Problem is, that everything works fine for a while... but when i
work a little bit with the app, the app is freezing.... and it's not
repeatable... Why?
Another question: Is it possible to stop the BgWoker at my own (like:
bgWorker.Stop() ...)

Thanks for any help...

Regards
Carsten
Thanks for your help... but it' still not working.. i'm frustrated....
Here my methode actualizeClusterSizes, which is processed in the _DoWork :
public void actualizeClustersSizes()
{
this.inProgress = true;
int pos = this.currentStep < this.maxSteps ? this.currentStep : 2;
string category = this.categories[pos][0];
SieveMapCluster[][] clusters = this.cACTIVE;
//connect to the db
DataManager.DB.connect();
//go through the cateory array and get the size of the clusters
int countSteps = 0;
foreach(SieveMapCluster[] cs in clusters)
{
foreach(SieveMapCluster c in cs)
{
countSteps++;
}
}
int countCurrentStep = 0;
foreach(SieveMapCluster[] cs in clusters)
{
foreach(SieveMapCluster c in cs)
{
string cQ = "";
// if no KEYWORDS set the sql is a little bit different..
if(KeywordManager.KEYWORDS.Length == 0)
{
cQ = " WHERE(";
}
else
{
cQ = " AND(";
}
int i=0;
foreach(string s in c.Keywords)
{
cQ += category + " = '" + s + "' ";
if(c.Keywords.Length>1 && i < c.Keywords.Length-1) cQ += " OR ";
i++;
}
countCurrentStep++;
int v =
System.Math.Min(100,(int)(this.progressBar.Maximum*((double)((double)countCurrentStep/(double)countSteps))));
this.bgWorker.ReportProgress(v);
cQ += ")";
DataManager.DB.ClusterQuery = cQ;
string count = "SELECT COUNT(*) FROM main" + DataManager.DB.addQuery();
try
{
c.CSize = DataManager.DB.getClusterSize(count);
}
catch(Exception ae)
{

}
}
}
DataManager.DB.close();
this.inProgress = false;
}

Whats wrong here?
 
Yeah, thanks... t thought, that getting a variable from a ui-element
doesn't mean touching a ui-element.. my fault...

But i have one question.
Before i start the BW i clean the view, that means i have a panel with
panel on it (to represent some cluster from a library), then the user
interacts... i Clear all the panels from the panels and start the BW
doing some DB-things... BUT after Clear i have to set a
Thread.Sleep(100) because if i don't do that, the panels are not removed
from the panel before starting the BW, and that looks not very beautiful..
Is there any chance to Clear or Remove panels from a panel so that they
are thron away in THIS moment i would like...
(Sorry for my English, i'm on the way to a lecture.. :-))

Regards
Carsten
 
Sorry, I don't understand the problem. Can you post a repro so I can try it
here? Let me know if you replace the Sleep with an Application.DoEvents if
the problem goes away. You should not need to do that though so please post
a small repro so I can look at it.

Cheers
Daniel
--
http://www.danielmoth.com/Blog/


Carsten Marx said:
Yeah, thanks... t thought, that getting a variable from a ui-element
doesn't mean touching a ui-element.. my fault...

But i have one question.
Before i start the BW i clean the view, that means i have a panel with
panel on it (to represent some cluster from a library), then the user
interacts... i Clear all the panels from the panels and start the BW
doing some DB-things... BUT after Clear i have to set a Thread.Sleep(100)
because if i don't do that, the panels are not removed from the panel
before starting the BW, and that looks not very beautiful..
Is there any chance to Clear or Remove panels from a panel so that they
are thron away in THIS moment i would like...
(Sorry for my English, i'm on the way to a lecture.. :-))

Regards
Carsten
 
Back
Top