Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

vb timer seem to increase mem usage, how can that be stopped?

Posted on 2008-06-17
16
Medium Priority
?
312 Views
Last Modified: 2012-06-22
Hi. I am trying to read the color of a pixel on the computerscreen every 0.1 seconds. The problem i have is that the mem usage (seen in Windows Task Manager / processes) increases rapidly (especially when the screencolor changes) and after a while i get a system.outofmemory exception
Is there any way of clearing cache memory that is stacked or maybe someone has an even smarter solution.

Try for example this code:
Public Class Form1
    Private Declare Function GetDC Lib "user32" Alias "GetDC" (ByVal hwnd As Integer) As Integer
    Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As Integer, ByVal x As Integer, ByVal y As Integer) As Integer
 
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Timer1.Interval = 100
        Timer1.Enabled = True
    End Sub
 
    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Dim testcolor As Integer
        testcolor = GetPixel(GetDC(0), 100, 100)
        Button1.BackColor = System.Drawing.ColorTranslator.FromOle(testcolor)
    End Sub
 
End Class

Open in new window

0
Comment
Question by:soriega
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 4
  • 3
  • +1
16 Comments
 
LVL 25

Expert Comment

by:SStory
ID: 21807382
I can't imagine VB being fast enough to read it that quickly. (is this VB or Vb.NET?)

Also I think GetDC may take a while and you have to ReleaseDC?

You are probably getting out of memory for not doing a ReleaseDC.

You also may be reentering the Tick event before the prev event is processed.  Maybe a boolean flag that exits the tick event when set so that it doesn't process any more until it finishes the current one.

Here is an FAQ from Bob Powell on doing it in Vb.NET:

http://www.bobpowell.net/eyedropper.htm

0
 
LVL 21

Expert Comment

by:mastoo
ID: 21807426
Shouldn't you bet loading GetDC(0) into a variable and calling ReleaseDC on each timer tick?
0
 

Author Comment

by:soriega
ID: 21807508
OK thanks. I am not to experienced on using "releaseDC" , do you have a code snipplet maybe?
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 21

Expert Comment

by:mastoo
ID: 21807626
If I take the shortcut of omitting error handling as an exercise for the student...

Public Class Form1
    Private Declare Function GetDC Lib "user32" Alias "GetDC" (ByVal hwnd As Integer) As Integer
    Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As Integer, ByVal x As Integer, ByVal y As Integer) As Integer
    Private Declare Function ReleaseDC Lib "user32" Alias "ReleaseDC" (ByVal hwnd As Integer, ByVal iDc As Integer) As Integer
 
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Timer1.Interval = 100
        Timer1.Enabled = True
    End Sub
 
    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Dim testcolor As Integer
        Dim iDc as integer = GetDC(0)
        testcolor = GetPixel(iDc, 100, 100)
        ReleaseDC( 0, iDc)
        Button1.BackColor = System.Drawing.ColorTranslator.FromOle(testcolor)
    End Sub
 
End Class
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 21807648
Try this out:
    Private Declare Function GetDesktopWindow Lib "user32" () As IntPtr
    Private Declare Function GetWindowDC Lib "user32" (ByVal hwnd As IntPtr) As IntPtr
    Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As IntPtr, ByVal hdc As Integer) As Integer
 
    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Dim desktopHwnd As IntPtr = GetDesktopWindow()
        Dim desktopHdc As IntPtr = GetWindowDC(desktopHwnd)
        Dim testcolor As Integer = GetPixel(desktopHdc, 100, 100)
        ReleaseDC(desktopHwnd, desktopHdc)
        Button1.BackColor = System.Drawing.ColorTranslator.FromOle(testcolor)
    End Sub

Open in new window

0
 
LVL 25

Expert Comment

by:SStory
ID: 21807659
GetDC, like many graphic API calls returns a handle.  If you want to release it you need that handle.  I said this in the first post.

However, I wonder if the time that it takes to complete may be longer than 100ms, and if so, it may get called multiple times before the first time completes and that could cause problems.
0
 
LVL 21

Assisted Solution

by:mastoo
mastoo earned 400 total points
ID: 21807830
I don't think any of those calls yields to the message pump, so as long as the forms timer is used (as opposed to the threading timer) you won't get reentrancy.  Having said that, I'll certainly agree the guard variable is a good practice to get into.
0
 

Author Comment

by:soriega
ID: 21807904
Yepp i am aware about the problem that it might be "stacking" of timer things. However, if i increase the timer.interval=3000 it still keeps increaseing mem usage. It seems to increase more every time the color of the pixel changes? I have implemented both these presented solutions, however none of them fixes the problem with increased memory usage.
0
 

Author Comment

by:soriega
ID: 21808115
The easiest way to watch this problem is to open youtube.com and let the application read from a spot where the color changes on the screen. I can se Mem usage increasing slow and steady all the time...
0
 

Author Comment

by:soriega
ID: 21808182

Here is actually a solution to the problem ! Very weird, but this actually decreases the mem usage to a minimum:
            Me.WindowState = FormWindowState.Minimized
            Me.WindowState = FormWindowState.Normal

Not nice and clean, but it works
0
 
LVL 25

Assisted Solution

by:SStory
SStory earned 400 total points
ID: 21812248
Are you calling the ReleaseDC?

Here is an alternate way of getting pixels..a class for C# that I thought you might also find interesting:
http://www.mdibb.net/net/faster_pixel_manipulation_with_getpixel_and_setpixel_in_net/

I would have thought the solution by Idle_Mind would have worked.  Of course we all know that the memory reported in Task Manager is incorrect for DotNet apps, but I wouldn't think API calls made from DotNet would suffer this problem.  Maybe Vista has fixed the issue, but in XP you can't believe the numbers...which appear really huge.
0
 
LVL 86

Accepted Solution

by:
Mike Tomlinson earned 800 total points
ID: 21812780
The out of memory exception should be solved by the ReleaseDC calls as DC's are a limited resource.

The memory usage decreasing after minimizing the window is indicative that things are working CORRECTLY.  If you had a true memory leak then the app would not return the resources it had used to the operating system.  The garbage collector does not run as often as most people feel it should...supposedly when the operating system as a whole needs memory the .Net framework will release some of its "hogged" resources automatically.

"My app is using huge amounts of memory and/or has a memory leak" is a very common symptom here at EE.  Most of the time it is determined that in fact there is NO memory leak though!
0
 

Author Closing Comment

by:soriega
ID: 31468127
I will try to use the Release thing. Any other things out of these where "release" style should be used?
GetWindowRect
FindWindow
mouse_event
SetWindowPos
EnumWindProc
FindWindowEx
GetWindowText
EnumChildWindows

0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 21813103
Those APIs are "safe"...  =)
0
 

Author Comment

by:soriega
ID: 21813326
Thanks
0
 
LVL 25

Expert Comment

by:SStory
ID: 21814227
As a follow up to your question about other API's...
I don't see any in that list that should cause you a problem.

Mainly when you get a DC, or  a resource like Bitmap, Fonts or other items to "Draw" with, you select them, store their prev values, and restore that when through.  Much of GDI works like this.  You get it, use it and give it up or you have memory leaks.
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction While answering a recent question about filtering a custom class collection, I realized that this could be accomplished with very little code by using the ScriptControl (SC) library.  This article will introduce you to the SC library a…
Have you ever wanted to restrict the users input in a textbox to numbers, and while doing that make sure that they can't 'cheat' by pasting in non-numeric text? Of course you can do that with code you write yourself but it's tedious and error-prone …
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…
Suggested Courses

660 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question