Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Timer + memory 2

Status
Not open for further replies.

vlitim

Programmer
Sep 2, 2000
393
GB
I have a timer on a form which fires every second, one of the machines I have installed it on crashes after a couple of hours stating insufficient memory. The program is likely to be on all day, is there anyway of getting round this!?
 
What is the code in the timer, since that is what is likely to be the root cause of the problem?
 
all that happens is it starts when the form loads then on every firing it checks two tables against the current time, then updates a taskbar!


 
'all that happens' is one of those weasel phrases that often catches us out. I remember writing a C program that crashed in a particular function. 'All that happened' in that function were that two strings got concatenated - but a tiny error in pointer arithmetic meant that it sometimes wrote to memory I hadn't actually alloc'd for the purpose.

So it might be worth you posting the code here so we can have a quick look. Otherwise, all your effectively saying to us is: why is my computer crashing?
 
Hopefully your on NT, then you could do this.

Run your program and open the Task manager. Go to the Processes tab and click the top to sort by Mem Usage. You will then be able to see if you have a Memory Leak or if the program is simply catching some sort of error that causes the problem.

p.s. If it's a memory leak you will see the Mem Usage slowly rise and rise, increasing with time. Craig, mailto:sander@cogeco.ca

Bow Before me for I am ROOT
<Beer>Happiness</Beer>
 
HI vlitim,

I am also trying to get a timer and a query to run itself every few seconds. How did you do it?

A piece of code with time delayed firing sequence would be most appreciated.

Thanks

x44
 
2 ways.

1) Add a timer control to your form.

2) Add a looping piece of code.

Do
If Now() <> dtTime then
dtTime = dateadd(&quot;m&quot;, Now(), 5) ' Add 5 minute interval
'Do your code
End if
DoEvents 'You have to have this line of code.
Loop Craig, mailto:sander@cogeco.ca

Bow Before me for I am ROOT
<Beer>Happiness</Beer>
 
Thanks for reply Craig.

You just hit the root of my problem. MyTable receives updates from a linkedSource. No Forms here, hence no events and nothing to hang on them. Updates come at randon intervals, so I run queries every miute (I wish I could do it every 30 seconds!) &quot;just in case&quot; something came in.

I want to ask: will what you wrote work without tables?
If Yes, how?

Thanks again.

Dmitry
 
What tables.

How are you running this program in a VB script or as a windows service.

To change it to seconds here ya go.

Do
If Now() < dtTime then
dtTime = dateadd(&quot;s&quot;, Now(), 30) ' Add 30 second interval
'Do your code
End if
DoEvents 'You have to have this line of code.
Loop

Craig, mailto:sander@cogeco.ca

Bow Before me for I am ROOT
<Beer>Happiness</Beer>
 
Well, it is relatively simple to write a timer class that doesn't need a form. However, why not just have an invisible form with a normal Timer on it?
 
Pardon a newbie's question,
but how exactly do you get a Timer into invisible form?
 
Gotta dash to the pub. I'll try to reply when I get back. Answer may well be somewhat garbled though...
 
Thanks, strongm!
Does &quot;m&quot; stand for &quot;Mike&quot;? I worked with Mike Strong from MIS a coupple years ago. Does &quot;WLDC&quot; ring any bell?

In any event, look forward to your reply.

Dmitry
 
Oh, I should also say that due to certain quantities of alcohol I am currenly unable to answer the question you asked (for now)
 
In that case strongm, may I suggest the following API Call:

Private Declare Sub Sleep Lib &quot;kernel32&quot; (ByVal OverNight As Long)

Private Sub Mike_GetFocus()
Sleep <whatever it takes>
End Sub

[thumbsup]
Good Luck
------------
Select * from Users where Clue > 0
0 rows returned
 
Ok, Dmitry, here's an illustrative answer to your question.

Add two forms to your project. Drop 2 command buttons onto Form1. Rename Form2 as frmTimer (not essential, but it'll help make the minor code that follows slightly easier to understand), and set its Visible property to false. Drop a Timer onto frmTimer, make sure it is enabled and set an appropriate Interval (say 1000). Drop the following code into frmTimer:
[tt]
Option Explicit

Private Sub Timer1_Timer()
Debug.Print &quot;frmTimer Event&quot;
End Sub
[/b]
Right, now drop the following code into Form1:
[tt]
Option Explicit

Private Sub Command1_Click()
Load frmTimer ' Loads invisible form, which causes all contained controls to instantiate.
End Sub

Private Sub Command2_Click()
Unload frmTimer
End Sub
 
Ok, create an ActiveX exe project (mine's called clsTimer). Set the instancing to SingleUse. Add a module (I call it vbTimerClassSupportFunctions), and drop in the following code:
[tt]
' This whole support module exists merely to get around the fact that we cannot use AddressOf
' in a class module. Additionally we'll need to make our class SingleUse to ensure that each vbTimer get's it's own
' timerproc
Option Explicit
Public CurrentTimer As vbTimer

' Use this to get around one of the limitations of AddressOf
Public Function ReturnAddress(lpAddress As Long) As Long
ReturnAddress = lpAddress
End Function

' This is the timer callback function
Public Sub TimerProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal idEvent As Long, _
ByVal dwTime As Long)
Call CurrentTimer.RaiseIt(hwnd, uMsg, idEvent, dwTime)
End Sub

Public Function TimerProcAddress(myTimer As vbTimer) As Long
Set CurrentTimer = myTimer
TimerProcAddress = ReturnAddress(AddressOf TimerProc)
End Function
[/tt]
Now, if you don't already have one add a class module (I call mine vbTimer), and drop in the following code:
[tt]
Option Explicit

Private Declare Function SetTimer Lib &quot;user32&quot; (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib &quot;user32&quot; (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long

Private mvarEnabled As Boolean
Private mvarInterval As Long
Private mvarTimerID As Long

Public Event Timer()

Public Property Let Interval(ByVal vdata As Long)
mvarInterval = vdata
End Property


Public Property Get Interval() As Long
Interval = mvarInterval
End Property

Public Property Let Enabled(ByVal vdata As Boolean)
mvarEnabled = vdata
ToggleTimer
End Property

Public Property Get Enabled() As Boolean
Enabled = mvarEnabled
End Property

Friend Sub RaiseIt(ByVal hwnd As Long, ByVal uMsg As Long, ByVal idEvent As Long, ByVal dwTime As Long)
If idEvent = mvarTimerID Then
RaiseEvent Timer
End If
End Sub

Private Sub Class_Terminate()
If mvarTimerID Then
KillTimer 0, mvarTimerID
End If
End Sub

' Should timer be activated?
Private Sub ToggleTimer()
If mvarEnabled = True And mvarInterval > 0 Then
mvarTimerID = SetTimer(0, 0, mvarInterval, TimerProcAddress(Me))
ElseIf mvarTimerID Then
KillTimer 0, mvarTimerID
mvarTimerID = 0
End If
End Sub
[/tt]
You can only use the compiled version of this in other projects, as the VB IDE does not actually support single instancing.

In use, because we are using an event, the vbTimer object will need to be hosted in a proxy class module (or a form module - but we want to avoid forms...). Here's an example. Create a new, formless project, with Sub Main as the startup. Add a reference to clsTimer. Add a Class module (I call mine TimerProxy[), and drop in the following code, which demonstrates two timers:
[tt]
Option Explicit

Public WithEvents myTimer1 As vbTimer
Public WithEvents myTimer2 As vbTimer

Private Sub myTimer1_Timer()
Debug.Print &quot;Timer1 Event&quot;
End Sub

Private Sub myTimer2_Timer()
Debug.Print &quot;Timer2 Event&quot;
End Sub
[/tt]
Finally drop the following the code module:
[tt]
Option Explicit

Private Sub main()
Dim lp As Long
Dim starttime As Date
Dim endtime As Date

Dim mytimers As TimerProxy
Set mytimers = New TimerProxy

Set mytimers.myTimer1 = New vbTimer
Set mytimers.myTimer2 = New vbTimer

mytimers.myTimer1.Interval = 1000
mytimers.myTimer1.Enabled = True

mytimers.myTimer2.Interval = 2000
mytimers.myTimer2.Enabled = True
starttime = Now
endtime = DateAdd(&quot;s&quot;, 60, Now)

Do Until Now = endtime
DoEvents
Loop
End Sub
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top