I am using GDI+ to draw to the graphics object when an OnPaint event occurs. However, if you draw lots of things, the form becomes unresponsive until all of the drawing is done. Is there anyway to put the OnPaint event in another thread, so the form can remain responsive while the painting occurs

GDI+ Multi Thread
Englestone
We don't do this multi-threaded, but with optimized alchoritmes and long nights of profiling to find bottlenecks
Don't forget you can cache things and you don't need to create object in the paint event but you must re-use objects and get objects from cache.
Use a buffer to buffer unchanged pieces, as long as a part doesn't change you don't need to update that buffer piece.
Friend Li
Then you can cache the Pen, Brushed or even an Bitmap representation withing the instances.
Grey Young, please specify wish part you are intrested in and i will provide a sample.
Lauren Lavoie - MS
I thought I could solve this problem by passing the onPainteventargs e variable to another method using the beginInvoke method (for asynchronous processing) unfortunately, once you exit the onPaint method e becomes null or inaccessible.
Something like this:
private void Somemethod( Painteventargs e)
{
}
private override OnPaint(object sender, Painteventsargs e)
{
base.OnPaint();
this.beginInvoke(DelegatetoSomemethod, e paramater)
}
Unfortunately, this doesn't work. Any other ideas
Thomas van der Heijden (old)
Assuming you still need some help with this one, if you reply with your OnPaint code, I should be able to help.
My intial thought is there is perhaps something wrong with your paint code as normally this would not slow down the UI (user interface).
Gecko2648
Try and avoid creating classes in the onpaint method - or at least only do it once. I guess it depends how dynamic your layout is, but you can pre-create the rectangles (a rectangle collection), then in the onpaint event you just draw them.
If the rectangles are being moved around, just access the collection and change their location.
The onpaint event should be left for painting, not class creation.
Charles Petzold wrote a good book on all this kind of stuff "Programming Microsoft Windows with C#"
HTH,
Shajan Dasan
Can you put a working example using the method described here I have always had the same problem with the event args being invalidated.
Mister T7718
We have a Excel like control, one big control that can contain more then 500.000 cells. No multi-thread needed, only optimized algortimes and caching of unchanged graphics.
Try if something is visable before painting, here is little example:
protected override void OnPaint( PaintEventArgs e )
{
foreach(Cell cell in _cells)
{
if( e.ClipRectangle.IntersectWith( cell.Bounds ) )
{
cell.Paint( e.Graphics );
}
}
}
Simple, but efficient!
zelda
You can't put it on another thread.
The reason for that is you would need to pass PaintEventArgs e to the other thread. The problem with this is that as soon as your event returns (it is being run synchronously on the main thread) the eventargs object is changed by the code that threw the event. As such you would at best end up with a race condition (one that will almost always fail).
Cheers,
Greg
satyam
Perhaps that is the problem I'm having. I don't know how to correctly cache. At least, it seems like I'm missing that part.
I understand how to create some rectangles, hold a reference to them and then paint them in the OnPaint method. However, what about filling the rectangles, drawing strings, and other things that can be directly done to PainEventArgs.
For example,
protected
override void OnPaint(PaintEventArgs e){
base.OnPaint(e);e.Graphics.DrawRectangle(mypen, myrectangle);
}
You can create the rectangle, and Pen else where but what about filling the rectangle Can you fill the rectangle out of this method Also, what about drawing strings There has to be a good way to cache this information and to restore it OnPaint, I don't think I know how to do this right...
xishan shigri
Well, just out of curiosity, lets say you wanted to draw a thousand rectangles on a form in the OnPaint method, this will definitely slow down the UI, as it has to create the rectangles and then update the UI...
For (i = 0; i < 999; i++)
{
e.graphics.drawrectangle(new rectangle);
}
I was thinking that there is a better way to do this then putting it all in the OnPaint method... maybe not. Obviously, since this is being painted with no clipping region, in order to redraw one rectangle, you gotta re draw them all.
Felice
itsonlyme4
hi,
i think this might help you
//this will make your application wait to perform something if you
//do lots of typical operations and you want to slow it down to show the user the events
Application.DoEvents();
//this to make the application wait for milliseconds in iteration statments
System.Threading.Thread.Sleep(400);
but i have a question for how how can i learn drawing in C# is there a way to do that
hope this will help
Marco Sousa
You can't put it on another thread so far as I'm aware.
The other thing to do is use the plural methods wherever possible - ie DrawRectangles(array of rectangles) is faster than multiple calls to DrawRectangle(single rectangle).
HTH,
PaddyK
Yeah, I see how the clipping area re draws only the items needed to be drawn. Thanks for the code snippet.
Still I suppose there is no way to throw this on another thread
Thanks for your post.