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!?
'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?
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>
Do
If Now() <> dtTime then
dtTime = dateadd("m", 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>
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!) "just in case" something came in.
I want to ask: will what you wrote work without tables?
If Yes, how?
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("s", 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>
Thanks, strongm!
Does "m" stand for "Mike"? I worked with Mike Strong from MIS a coupple years ago. Does "WLDC" ring any bell?
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 "frmTimer Event"
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 "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "user32" (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 "Timer1 Event"
End Sub
Private Sub myTimer2_Timer()
Debug.Print "Timer2 Event"
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
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.