pro_vb thread: More asynchronous events.
ITimerNotify is a class with only one method:
'' return True to restart the timer
public function TimerExpiredRestart() as Boolean
end function
This is how a client can use MTimer.bas:
Implements ITimerNotify
.. code here...
StartTimer Me
private function ITimerNotify_TimerExpiredRestart() as boolean
... do what you want here and do not worry about
... reentrance, because the timer is now disabled
...
TimerExpiredRestart = True '' or false, you decide
end function
MTimer.bas can be modified to add a timer interval like:
Public Sub StartTimer(obj As ITimerNotify, optional byval millisec as long
100)
Set m_obj = obj
m_lTimerID = SetTimer(0, 0, millisec, AddressOf TimerProc)
End Sub
A little trickier is to have multiple timers, because the SetTimer callback
must
be in a bas module. The easiest solution is to have an pool of let's say ten
callbacks, and keep an array of ITimerNotify objects. When a client asks for
a timer, loop through the array until you find an empty slot (if not found,
return an error code) and set the corresponding callback. This is a
technique
often using for subclassing multiple windows.
-----Original Message-----
From: Padgett Rowell [mailto:padgett@i...]
Sent: Thursday, August 30, 2001 11:39 PM
To: professional vb
Subject: [pro_vb] RE: More asynchronous events.
I like your timer class can we have a usage example please?
Where does the ITimerNotify object come from? How is it defined?
padgett
-----Original Message-----
From: Marco Straforini [mailto:marco.straforini@c...]
Sent: Thursday, 30 August 2001 6:53 AM
To: professional vb
Subject: [pro_vb] RE: More asynchronous events.
Stuart,
I like your code, thanks to share it with us.
I just had few ideas, maybe are good maybe not...
Your clients have to reference to two projects and
creates two classes, and I was wondering if it was possible
to make it a little simpler. This is my idea.
Instead of using an intermediate activeX (the little pig)
that both client and server has to know about, why not
making the piggy create the server and act as a dispatcher
only (I did something like that in a previous life, when I
was working in C on Unix... only sockets at the time)
The client has only to create piggy (with events) that in
turn will create the server (with events). The drawback is
that piggy has to expose all the methods of the server,
and dispatch the calls to it (you can do something more
elaborated using the implements keyword).
When piggy receives an event from the server, it adds it
to private a collection and start a timer. In the timer, it gets
the first item of the collection and raise the event to
the client. If the client blocks, the server is still alive.
After the message is sent, the timer is restarted if there
are more elements in the queue. Only one timer is needed.
The beauty with this is that the server does not know anything
of the intermediate server (the cute little pig) and you do
not have to modify it. Just send events the normal way. More than
that, clients can still use the server 'old way', and block
events. Otherwise, they can create only the piggy guy and
do not have to know anything about the server.
What do you think? Just a thought, if I had more time I will try
it myself.
m.
PS: instead of using an empty form just to have timers, you
can consider using the SetTimer API. This is the bas module
(stripped a little) that I use. The user must implement the
ITimerNotify interface that has only the method
TimerExpiredRestart (as boolean) that must return True to
restart the timer. You can easily modify it if you need
more than one timer.
<MTimer.bas>
Option Explicit
Private m_obj As ITimerNotify
Private m_lTimerID As Long
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
Public Sub StartTimer(obj As ITimerNotify)
Set m_obj = obj
m_lTimerID = SetTimer(0, 0, 100, AddressOf TimerProc)
End Sub
Private Sub TimerProc(ByVal hwnd As Long, ByVal msg As Long, ByVal id As
Long, ByVal currenttime As Long)
KillTimer 0, m_lTimerID
m_lTimerID = 0
If m_obj.TimerExpiredRestart Then
m_lTimerID = SetTimer(0, 0, 100, AddressOf TimerProc)
Else
Set m_obj = Nothing
End If
End Sub