views:

63

answers:

2

Hey all, I'm using a BackGroundWorker to avoid UI freezing while working with a method which uses wait handles, and this method is used to draw on a panel in the UI and has panel invalidation inside.

something()
{
  draw()
  panel.invalidate()
  A.waitone(500)

}

The problem is, sometimes the Worker gets stuck in the middle of the drawing and when I re press the worker start button it works again and doesn't get stuck, that means it wasn't stuck due to being busy, so the drawing which got stuck not the Worker, but I have invalidation after each draw, so any ideas??

+1  A: 

You should not be accessing UI elements from a method called from a backgroundworker.

(From comments)

I'm trying to draw something step by step that's why I need the waithandles

If you want to draw step by step, delaying between each step, then I'd be inclined to use a System.Windows.Forms.Timer rather than waiting on a waithandle. Set the timer to fire at the frequency you want, and when it fires draw a bit more of whatever it is you're drawing.

Joe
Why??!?! I can't accomplish what I want without accessing the UI elements from the BackGroundWorker.
Shaza
Why ? Because the backgroundworker runs in its own thread, and you can't access GUI elements from other threads than the GUI thread. There might be a way to pass inn the stuff you need to the background worker, but you need to tell us specifically what you're trying to do.
nos
I'm trying to draw something step by step that's why I need the waithandles and that's why I need to invalidate the panel and I don't want the UI to freeze while drawing so I need to use the BackGroundWorker.
Shaza
If you need to access UI in the background thread, you should use the ReportProgress method (which runs on the UI thread), and manipulate the UI from there, passing a 'user state' to switch among different actions.Using Invoke on the background thread itself, totally defeats the purpose of a BackgroundWorker, since you could just use a simple Thread.
BladeWise
+1  A: 

If you want the background process to update the UI, you need to use the control's "Invoke" method (this will ensure that the code is run in the UI thread, and not in the background thread):

something()
{
  panel.Invoke(new Action( () => {this.draw(); panel.Invalidate();} );
  A.waitone(500)
}

Or, without the Lambda

something()
{
  panel.Invoke((MethodInvoker)delegate{ this.draw(); panel.Invalidate();});
  A.waitone(500)
}

EDIT: after seeing new comment on other answer -- you could wrap each an every control call in an 'Invoke' call during your threaded processing, so instead of calling the 'draw()' method itself in the invoke, have the draw() method use the Invoke whenever it needs to update the UI.

Dr Herbie
Thanks, I tried the Second one and that worked perfectly, but I'm still worried about getting stuck again, this seems to be craziness, but should I trust invoke?
Shaza
I use invoke a lot for long running tasks to show a progress/cancel dialog to the user -- hasn't failed me yet :)
Dr Herbie