Link to home
Start Free TrialLog in
Avatar of amrelgarhy81
amrelgarhy81Flag for Egypt

asked on

DrawImage(..) Method decrease the performance too much

Hello,

Ima using the DrawImage Method to drow multi Images on a pictureBox control using a timer but i found that this method make the performance too bad,
There is another method in .Net i can use instead???

Please help,

Thanks
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Can you give us a bigger picture of what you are doing so we can suggest possible different approaches?
Avatar of amrelgarhy81

ASKER

What iam doing is a user control:
It is inherited from pictureBox control and i use a timer to change the images in the picture box and i do some effects while changing beween images so i use the drawImage method to do that effects.
And that made me see the lake in performance.
Please ask if you need more.
Understood me??
Yes...but it's too vague to really make any good suggestions off of...

How big are your images?
How often are you changing them?
Where are you storing the different images?
What kind of effects are you making?

Etc...

There are many things that can affect "performance"...
Yes i Know tha manythings can affect the performance but what iam asking about is that the drawImage method make decrease in performance, there is another function in .Net that can replace it?

Some effects like:
Draw a new image moving and scaling from left to right or up to left
You know somthing near to powerPoint effects.
ASKER CERTIFIED SOLUTION
Avatar of Pigtor
Pigtor
Flag of Mexico image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
So Pigtor
Should i draw on another control or donn't use the drawImage method,
Note i need it to be a control because i will deal with it  as a user control later,
And i found that the big performance problem is in the DrawImage method.
DrawImage is not slow, GDI+ is slow
You could find a lot of information on bobpowell website:
http://www.bobpowell.net/why_so_slow.htm

If your component demand a lot of graphics, you should better use DirectX.

Answering your question, DrawImage is not slow, but you should better use DrawImageUnscaled, because scaling an image can slow down the rendering.

I hope that information helps.

Victor
Ok, but small question:
PowerPoint and flash uses directx?
I tryed the DrawImageUnscaled method but nothing happened new

What can i do?
Avatar of CuSo4
CuSo4

On wich thread are you calling DrawImage? I believe it shouldn't be used in the timer-thread itself, as it will result in semi-freezing windows. Can you give us a sample of your code?
Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick

            Dim mx As New Matrix()
            mx.Translate(0, mH, MatrixOrder.Append)
            g.Transform = mx
            mH = mH + (Me.Height / 10)
            g.DrawImage(Me.currentImage, 0, 0, Me.Width, Me.Height)
            If mH > 0 Then
                Me.Image = Me.currentImage
                mH = -Me.Height              
                Me.Timer2.Enabled = False
            End If


End Sub
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I found no diffrence in the performance.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Timer  Interval  = 1
we can use e-mails here to sent the sample i have?
You won't get the Timer control to fire properly with an Interval of 1!

The lowest you will likely see "proper" timing is somewhere around 25, but it may be as high as 50 on some older systems.
by the way thats not the problem
the problem the my processor get very hight while running the draw image method, in a timer , on a new thread, or on the main thread.
Of course...your processor is probably pinged at 100% because there isn't any "pause" between events with a Timer interval that low.  The events are all stacked up against each other in your message queue making them run essentially as if they were in an inifinite loop.  

The same would be true if you placed the code into a different thread but did not provide a "pause" inbetween paints via the Sleep() method.

Just to prove it...bump up your interval to 100 and see if your processor usage drops down.  If it doesn't then you are attempting to do too much processing in the timer event.
I heared from someone is that the problem is in the GDI+ its self becuase it dosn't work directly with the hardware like the previous GDI in vb6 and heared too that GDI+ is not a managed classes it is just API methods called from the .net
Idle_Mind is right about the Timer Interval, and that's probably also why your processor utilisation gets that high.

@Idle_Mind: Sorry about the thread-confusion, I didn't know Timer events ran on the Form's main thread...
"I didn't know Timer events ran on the Form's main thread"

The System.Windows.Forms.Timer (it is the only one with a Tick event) runs on the main UI thread.

The other two Timers (System.Timers.Timer and System.Threading.Timer) run in their own thread.
Ok, good experts
I will try but small question:
suppose i used it without any timeres or threads, i used it in a loop it will be worest performance right?

And if i made "pause" between events the animation of the image will cut and continue, cut and continue.



That may just depend on how long the pause is.  There may not be that much noticeable difference to the end user.  It just depends on what you're doing.  Experiment with the Interval property...



A small call to Sleep() can greatly reduce CPU usage:

    System.Threading.Thread.Sleep(25)

The problem with moving the painting to a different thread is that you need a delegate to properly marshal the call from your thread back onto the main UI thread.  This causes additional overhead on the application, especially if you are "firing events" in rapid succession as you are.

A common misconception is that threading "frees up" the main UI.  If a thread does NOT pause, and continually fires an event that the main UI must handle, then the main UI will be continually process the threads event.  This essentially nullifies the benefit of creating the thread in first place...
ok, i will try and send what will happen
Using timers and sleep is not a good idea.

You can use a Threading.Timer, but you will get the "Object is already in use" exception.  To correct this behavior you should use the SyncLock <Bitmap> statement, where <Bitmap> is a reference to the Bitmap you are drawing.
The best performance you will get is using a timer of 100 ms.  I have posted before the reason GDI+ is so slow.

You could use a non threading timer like System.Windows.Forms.Timer or a LOOP, but it will not help you so much, because when another process slows down the computer, your GDI+ graphics will have a strange behavior.
For example, your image draws in 200 ms, and your sleep or timer is 100 ms, this interval will hang your computer.  Other example, your image draws in 200 ms and your timer is in 300 ms., the same will happen when another process slows down the machine.

Other consideration you should take is the size of the image, a small image draws faster than a large image.  Try testing a large image (for exaple 4x the small image size)  The result will be more or less the same behavior it will have in slower machines.
Now, try using a larger image (16x the size of the small image) on your timer and you will understand what I'm talking about.

My sugestion, use GDI+ for images that doesn't change frequently and DirectX for advanced image manipulation like animations.
If you don't have no choice but using GDI+, I suggest using a Threading.Timer rather than Windows.Forms.Timer Or Sleep.

Thanks Pigtor for your comment i will try all what you said Pigtor,  Idle_Mind  and will tell you both what i got,
Thanks alot for your effort experts.
Pigtor...

How can i use the Threading.Timer?
Using events like the Windows.Timer?
Or should i use it like this sample in the .Net 2.0 Documentaion:
ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.NETDEVFX.v20.en/cpref12/html/T_System_Threading_Timer.htm
Use the following code. Call the StartTimer and StopTimer.
The TimerProc method is the event you are looking for.

-------------------------------------------------------------------------------------------------------

Private hTimer As System.Threading.Timer

Private Sub StartTimer(ByVal Interval As Integer)
     If Not hTimer Is Nothing Then Return
     hTimer = New System.Threading.Timer(New System.Threading.TimerCallback(AddressOf TimerProc), Nothing, Interval, Interval)
End Sub

Private Sub StopTimer()
     If Not hTimer Is Nothing Then
          hTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite)
          hTimer.Dispose()
          hTimer = Nothing
     End If
End Sub

Private Sub TimerProc(ByVal obj As Object)
'...Put here the code ...
End Sub

Thanks, Will try and tell you the result, but small question:
Using this timer will give diffrent performance results than using normal threading, using sleep?
I really don't see how using a System.Threading.Timer will be any different than the current implementation using a System.Windows.Forms.Timer.

You won't be able to get any "faster" firing interval.

Additionally you now have the overhead of marshalling the call from your thread back onto the main UI using Delegates and the Invoke() methods.

?
right, I will try and get the results,
Thanks alot
The timer interval can be changed using the Interval parameter in the StartTimer method.
You will not find differences between both timers, because both does the same.  But the difference is in the performance with big images, slow machines or faster timers.

To get the best performance for your graphics, you should make your own tests using bigger images and faster timers.  When you get an acceptable performance on your bigger images, change your images to their normal size and you will see a very good performance.

Or maybe the reason of the bad performance is the technique you are using to draw the window.
GDI+ is very extensive to be answered in one question.  Please go to this link:
http://www.bobpowell.net
On this site you will find a lot of tricks for performance and what to NOT do in GDI+