Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

VB6 (formless) Timer class

1,565 views
Skip to first unread message

2b|!2b==?

unread,
Jan 19, 2008, 11:48:13 PM1/19/08
to
I want to use a timer in a formless class

and declared a variable in my class like this :

Dim withEvents m_timer As Timer

when I tried to instantiate it like this:

set m_timer = new Timer()

I realized it wouldn't work (object not available in IntelliSense). I
googled and came accross a solution which uses the SetTimer/KillTimer()
functions - but it requires the callback function to have a particular
signature, and to be defined in a module (.bas) file

What I am trying to do is to use a timer to simulate asynchronous
processing of events. So I want different 'event classes' each of which
handles different events. Something like this:

ClassEventA:

dim m_timer as MyTimer

Sub m_timer_Time()
'Switch off timer
'Do custom processing here
End sub


Does anyone know how I may do this ?


One other question relating to this is that of the lifespan of the
EventClass - once the timer has fired and the custom processing has been
done, the EventClass has done its job - and it needs to be 'released'
from memory - since there is no explicit 'delete' in VB:

i). At waht point will the EventClass be collected by the garbage
collector ?
ii). Can I force the object to be 'freed' once it has done its job? -
otherwise I could potentially be faced with several thousand 'dead
objects after a few hours of running

Steve Easton

unread,
Jan 20, 2008, 12:21:25 AM1/20/08
to
You can have a timer in a module.
You access it by using the module name.

For example type: With modulename. and then timer1 will be in the list
Typing: With modulename.timer1
.
will expose the properties of timer1.

There's probably a better way, but it works for me.

--

Steve Easton


"2b|!2b==?" <us...@domain.invalid> wrote in message news:9J6dnTk5JfFoEQ_a...@bt.com...

2b|!2b==?

unread,
Jan 20, 2008, 12:32:59 AM1/20/08
to

Steve Easton wrote:

> You can have a timer in a module.
> You access it by using the module name.
>
> For example type: With modulename. and then timer1 will be in the list
> Typing: With modulename.timer1
> .
> will expose the properties of timer1.
>
> There's probably a better way, but it works for me.
>

How do you raise timer events? (IIRC, you can't raise events in a module)

expvb

unread,
Jan 20, 2008, 1:08:05 AM1/20/08
to
Search the newsgroups or web for "vb SetTimer class" to find sample code.

> dim m_timer as MyTimer

This should be:

Dim WithEvents m_timer As MyTimer

The timer fires the event with the Raise statement. I have seen a full
sample somewhere, so you only need to just use it.


Steve Gerrard

unread,
Jan 20, 2008, 1:21:39 AM1/20/08
to
2b|!2b==? wrote:

> I want to use a timer in a formless class

> Does anyone know how I may do this ?

Karl does. He has several versions, including an OCX with a CTimer class, at
http://vb.mvps.org/samples/project.asp?id=TimerObj

As you discovered, a VB Timer needs a window, because it is a messaged based
timer, and you need a window to get messages (more or less). His code deals with
the callbacks of a timer that doesn't use messages.

> One other question relating to this is that of the lifespan of the
> EventClass - once the timer has fired and the custom processing has
> been done, the EventClass has done its job - and it needs to be
> 'released' from memory - since there is no explicit 'delete' in VB:

The lifetime of an object is from the first time it is created (Set X = New
...), until the last variable that references it goes out of scope, or it gets
set to Nothing.


2b|!2b==?

unread,
Jan 20, 2008, 1:42:56 AM1/20/08
to

Steve Gerrard wrote:

>>One other question relating to this is that of the lifespan of the
>>EventClass - once the timer has fired and the custom processing has
>>been done, the EventClass has done its job - and it needs to be
>>'released' from memory - since there is no explicit 'delete' in VB:
>
>
> The lifetime of an object is from the first time it is created (Set X = New
> ...), until the last variable that references it goes out of scope, or it gets
> set to Nothing.
>
>

But what of the case where the object has an active timer that is set so
that it can do some 'async' processing - suppose we have this code

Sub ReceiveSignal()
set oSignalEvent = new AsynchEvent '//has timer
oSignalEvent.SetData(someData) '//sets data, activates timer and
returns
End Sub


Sub oSignalEvent_Timer()
m_timer.enabled = false

'Do Processing

'Job finished now - So:
,when will this object be removed from
'memory - there are 1000's of signals coming in per hours
'and once the class has finished processing in its thread
'we have no further need for it
'
' Does anyone know when this object will be removed from memory?
' Is this legal syntax? (I don't think so)
Set me = nothing
end Sub

Steve Gerrard

unread,
Jan 20, 2008, 2:32:03 AM1/20/08
to
2b|!2b==? wrote:
> But what of the case where the object has an active timer that is set
> so that it can do some 'async' processing - suppose we have this code
>
> Sub ReceiveSignal()
> set oSignalEvent = new AsynchEvent '//has timer
> oSignalEvent.SetData(someData) '//sets data, activates timer and
> returns
> End Sub
>
>
> Sub oSignalEvent_Timer()

That event will never fire.
To receive events, you need to declare the variable WithEvents. You can't do
that with a local variable, it needs to be module level.

Private WithEvents mSignalEvent

Sub ReceiveSignal()
set mSignalEvent = new AsynchEvent '//has timer
mSignalEvent.SetData(someData) '//sets data, activates timer and
'returns. mSignalEvent is still good.
End Sub

Sub mSignalEvent_Timer()
' do as you wish...
' then release the object
Set mSignalEvent = Nothing
End Sub


2b|!2b==?

unread,
Jan 20, 2008, 2:41:39 AM1/20/08
to

Steve Gerrard wrote:

Will this result in asynchrous behaviour?. the idea is to allow a
component to be able to process many (potentially lengthy) operations,
whilst recieving generated signals at a high rate (i.e. at a rate higher
than it is processing the signals - ofcourse this only goes on for short
periods, but the important thing is that no signals are lost).

Does the code snippet above, provide the capability I described?.
Thanks

Steve Gerrard

unread,
Jan 20, 2008, 3:34:55 AM1/20/08
to
2b|!2b==? wrote:

> Will this result in asynchrous behaviour?. the idea is to allow a
> component to be able to process many (potentially lengthy) operations,
> whilst recieving generated signals at a high rate (i.e. at a rate
> higher than it is processing the signals - ofcourse this only goes on
> for short periods, but the important thing is that no signals are
> lost).
> Does the code snippet above, provide the capability I described?.
> Thanks

No, and in several ways. :(

First, that example declared one object that could receive events. If you mean
can you call ReceiveSignal again, before the first one gets done, the line set
mSignalEvent = new AsynchEvent would replace the first object with a new one.
The old one would be discarded as there would no longer be a reference to it.
You would need to declare several variables if you want to have several pending.

Second, and more serious, is that VB is single threaded. When you get the timer
event from Karl's code (assuming you use that), it will get processed on your
one and only VB thread. If you plan to do processing in that object, it will be
using your thread, so none of your other code will be executing. Even if that
timer did come in on another thread, so you had two or more going, none of the
other threads can do anything in your GUI, like trigger a display update,
without crashing VB.

Your best bet is do dig into making an ActiveX.exe. It is not a trivial process,
but it is doable. That would allow you to create objects in another process,
which can be configured to assign a separate thread to each object. Then they
can all play at the same time, and your app can continue with its business as
well.

Best of luck, you have some homework to do. :)


Larry Serflaten

unread,
Jan 20, 2008, 4:34:34 AM1/20/08
to

"2b|!2b==?" <us...@domain.invalid> wrote

> What I am trying to do is to use a timer to simulate asynchronous
> processing of events. So I want different 'event classes' each of which
> handles different events. Something like this:
>

> Does anyone know how I may do this ?
>

...


> One other question relating to this is that of the lifespan of the
> EventClass - once the timer has fired and the custom processing has been
> done, the EventClass has done its job - and it needs to be 'released'
> from memory - since there is no explicit 'delete' in VB:
>
> i). At waht point will the EventClass be collected by the garbage
> collector ?
> ii). Can I force the object to be 'freed' once it has done its job? -
> otherwise I could potentially be faced with several thousand 'dead
> objects after a few hours of running

There is no need to re-invent the wheel. VB ships with a Timer control
for use on its forms. You can use a form and timer without having to
show the form to the user. Doing so will let you use familiar code to
handle your task.

What you need to be concerned about is the thread used to execute
your tasks. If you sit and wait for incoming calls, things will go smoothly,
until you start responding to those calls. If you send a class off to do
some 'asyncronous' task, then part of your application's processing has
to include the time necessary to do that task. If that task is processor
intensive, then it wil effect your ability to respond to incoming calls.

After launching some number of those intensive tasks all trying to run at
the same time, you will find you are no better off than if you'd responded
to the calls directly. That is because your entire program can only execute
*one line of code at a time*.

If execution is taking place in a CPU hogging routine, (no DoEvents) then all
other processing in your application grinds to a halt until that routine has ended.
That includes the code you want responding to incoming calls.

Since you can only execute one line of code at a time, tasks (routines) that
have no DoEvents are going to run to completion, before any other task
you may have started. In essence you will have built a queue where the first
tasks in run to completion, ahead of any other task created.

If the 'queue' response is acceptable to you, why not build it as a queue,
(a bit simpler) instead of the not-so-asycnronous multiple tasks?

If the queue method is not acceptable, and you really want those tasks to
run asyncronously, then you need to give them their own thread, their own
process, in which to complete their task. Again, you need not re-invent the
wheel, VB's ActiveX exe projects run their own process and can be created
and controlled from your VB application.

So, in a nutshell, what is it you really want to do?

LFS

Michael C

unread,
Jan 20, 2008, 5:53:26 AM1/20/08
to
"2b|!2b==?" <us...@domain.invalid> wrote in message
news:mu6dnX2Md-bwCg_a...@bt.com...

> How do you raise timer events? (IIRC, you can't raise events in a module)

You can't create a timer in a module either. The module will not help in any
way at all as far as I can tell.


2b|!2b==?

unread,
Jan 20, 2008, 1:51:56 PM1/20/08
to

Larry Serflaten wrote:

> There is no need to re-invent the wheel. VB ships with a Timer control
> for use on its forms. You can use a form and timer without having to
> show the form to the user. Doing so will let you use familiar code to
> handle your task.
>

The problem with this is that the "Event classes" become unnecessarily
heavy (containing a form that has to be created, consumes resources, and
is not seen), plus I want to minimise the number of ActiveX controls I
use in my project. So if there is a way I can obtain the same
functionality without using an ActiveX control, I prefer it.

> What you need to be concerned about is the thread used to execute
> your tasks. If you sit and wait for incoming calls, things will go smoothly,
> until you start responding to those calls. If you send a class off to do
> some 'asyncronous' task, then part of your application's processing has
> to include the time necessary to do that task. If that task is processor
> intensive, then it wil effect your ability to respond to incoming calls.
>
> After launching some number of those intensive tasks all trying to run at
> the same time, you will find you are no better off than if you'd responded
> to the calls directly. That is because your entire program can only execute
> *one line of code at a time*.
>
> If execution is taking place in a CPU hogging routine, (no DoEvents) then all
> other processing in your application grinds to a halt until that routine has ended.
> That includes the code you want responding to incoming calls.
>
> Since you can only execute one line of code at a time, tasks (routines) that
> have no DoEvents are going to run to completion, before any other task
> you may have started. In essence you will have built a queue where the first
> tasks in run to completion, ahead of any other task created.
>
> If the 'queue' response is acceptable to you, why not build it as a queue,
> (a bit simpler) instead of the not-so-asycnronous multiple tasks?
>

Yes, this sounds interesting, could you tell me more - could you clarify
what you mean by "build it as a queue" ?

> If the queue method is not acceptable, and you really want those tasks to
> run asyncronously, then you need to give them their own thread, their own
> process, in which to complete their task. Again, you need not re-invent the
> wheel, VB's ActiveX exe projects run their own process and can be created
> and controlled from your VB application.
>
> So, in a nutshell, what is it you really want to do?

Actually threading etc are red herrings - my main objective is to be
able to handle large numbers of data coming in via WM_COPYDATA messages
- WITHOUT dropping one. I remember reading somewhere, that windows
messages remain on the message queue - either until they are read off
the queue by the application OR until they timeout (IIRC, the timeout is
specified in the SendMessage function call - but I'm sure someone will
correct me if I am wrong). However, I read a thread a little while ago,
where someone had asked the question as to whether messages sent by
WM_COPYDATA are guaranteed to be read of the queue by the application -
and IIRC, someone replied to say that if the application is busy (for
example, waiting for user import etc), then all bets are off, and the
messages will just "fall off" .... this is what I'm trying to prevent
... if messages can "fall off", then I need to find a way of preventing
that, thats what I'm trying to do in a nutshell.
>
> LFS
>
>
>

Mike Williams

unread,
Jan 20, 2008, 3:15:17 PM1/20/08
to
"2b|!2b==?" <us...@domain.invalid> wrote in message
news:Su2dnYI5iKE...@bt.com...

> The problem with this is that the "Event classes" become
> unnecessarily heavy (containing a form that has to be created,
> consumes resources, and is not seen), plus I want to minimise
> the number of ActiveX controls I use in my project.

Which ActiveX control are you referring to?

Mike


Larry Serflaten

unread,
Jan 20, 2008, 3:33:07 PM1/20/08
to

"2b|!2b==?" <us...@domain.invalid> wrote

> The problem with this is that the "Event classes" become unnecessarily

> heavy ...

> Actually threading etc are red herrings - my main objective is to be
> able to handle large numbers of data coming in via WM_COPYDATA messages
> - WITHOUT dropping one.

First, an analogy...

If you plan to call a friend over at 1:30, cook a pizza at 1:45, and watch the game
at 2:00, you don't use three separate clocks to determine when to begin those
tasks. You use one clock, and start the tasks at their appointed time.

Simlarly, you only need to use one from, with one timer, to manage all your
tasks, *not* one per task.

Also, saying threading is a red herring, is a bit like saying managing your
work in the VB IDE is a red herring, all you really want is the final program....

But to build the program, you need to use the IDE, and to run your program
you need to use a thread. You would be hard pressed to build a program
without using the VB IDE, and likewise, you'll run into problems with your
program if you don't consider thread management. Its fine if you want to
run all on one thread, but you have to be aware that all your code has to use
that one execution thread, (the one-line-at-a-time principle). To see the
problem, add two buttons to a new form and pase in this code:

Private Sub Command1_Click()
Dim i As Long
For i = 0 To 99999
Me.Caption = i
Me.Refresh
Next

End Sub

Private Sub Command2_Click()
MsgBox "click"
End Sub


Click the first button, and while the counter is counting, click the second.

Now consider what would happen if Command1 was your first task, and
Command2 was your second.....

When you enter a routine, you stay in that routine until it completes.
If that routine is a long running task, then ALL OTHER code in your
application grinds to a halt until that routine exits. For a further
demonstration add a timer to the form and add this code:

Private Sub Form_Load()
Timer1.Interval = 1000
End Sub

Private Sub Timer1_Timer()
Debug.Print "Tick Tock", Timer
End Sub


You'll note that even the timer does not fire while the counter is counting.
That is why you need to be concerned about thread managment, because
if your tasks go off and hog CPU cycles, you won't be able to respond to
incoming messages any better than the timer can respond to its events....

So, what you have to consider is, when you get a message, and have to go
act on it, does that action require a significant amount of time? If it does not,
then you might as well go do it, when it comes in. But, as you say, you might
miss a message if you do that, so you may want to put that message on an
internal queue and process it when you have time.

But the there begs the question, when you do go do whatever needs to be
done for a message, is that action going to effect your ability to pick up the
next message?

If it is, then you may have to consider getting more threads involved (ActiveX)
or, you may want to do the task in piecemeal fashion, only small parts of it at
a time, so as not to disturb the listening for new messages.

I tackled that situation some time ago and came up with a set of classes to
manage lazy (behind the scenes) processing. The resulting article is available
on the web, and if nothing else, it shows the use of SetTimer and KillTimer,
as you have been mentioning.

http://www.devx.com/vb2themax/Article/19890

Perhaps a read through that article may give you some ideas for your
current situation....

HTH
LFS


2b|!2b==?

unread,
Jan 20, 2008, 3:56:37 PM1/20/08
to

Thanks Larry - thats food for thought. Incidentally, I am familiar with
threading issues - infact, my backend library is multi-threaded, and
thats whats causing all these problems, since I'm using a non-rentrant
GUI (VB) as my frontend, so I'm having to marshall all my C/C++
callbacks etc via messages etc, it is a bit of a nightmare really. I
think I'll go away and read your article and see if it gives me any ideas.

Ralph

unread,
Jan 20, 2008, 4:09:52 PM1/20/08
to

"Larry Serflaten" <serf...@usinternet.com> wrote in message
news:e3vnUm3W...@TK2MSFTNGP04.phx.gbl...

>
> "2b|!2b==?" <us...@domain.invalid> wrote
>
> > The problem with this is that the "Event classes" become unnecessarily
> > heavy ...
>
> > Actually threading etc are red herrings - my main objective is to be
> > able to handle large numbers of data coming in via WM_COPYDATA messages
> > - WITHOUT dropping one.
>
> First, an analogy...
>
> If you plan to call a friend over at 1:30, cook a pizza at 1:45, and
watch the game
> at 2:00, you don't use three separate clocks to determine when to begin
those
> tasks. You use one clock, and start the tasks at their appointed time.
>
> Simlarly, you only need to use one from, with one timer, to manage all
your
> tasks, *not* one per task.
>
<snipped>

Great navigation advice. It dates back to the 18th century when mariners
were advised to never go to sea with two clocks. <g>

-ralph


Karl E. Peterson

unread,
Jan 23, 2008, 1:17:44 AM1/23/08
to
2b|!2b==? wrote:
> Will this result in asynchrous behaviour?. the idea is to allow a
> component to be able to process many (potentially lengthy) operations,
> whilst recieving generated signals at a high rate (i.e. at a rate higher
> than it is processing the signals - ofcourse this only goes on for short
> periods, but the important thing is that no signals are lost).
>
> Does the code snippet above, provide the capability I described?.

You'll need to take that example provided to you, and bend it to fit your specific
needs. No need for an actual timer class, per se. Just treat your working class as
that timer class, and rather than create a repeating timer callback in the module,
just create a one-shot deal by killing the timer on its first callback before
alerting your class. That oughta work, though I admit I haven't tested it.
--
.NET: It's About Trust!
http://vfred.mvps.org


0 new messages