By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,638 Members | 2,249 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,638 IT Pros & Developers. It's quick & easy.

Event handling precedence?

P: n/a
I have a piece of VB code (.NET 1.1 - VB 2003) that loads data from a
database through a timer. So the timer is setup and from it I call the
procedure that loads the latest records from the database. This works fine.

However, I attempt to notify the user when data accesses occur. The way I
attempt to accomplish this is by changing the background color of a label on
the form the user is looking at. I use red for when the database is opened,
yellow for data transfers and green for a successful completion of the
operation - and then I set the color back to its original gray background
after the operation.

If this is put inline in my code - for most (not all) accesses the notify
happens so fast you never see the color changes - so I want the change to
last for a second or so. So I set up another timer that essentially does:

if color = gray then set color red
if color = red then set color yellow
if color = yellow then set color green
if color = green then set color gray

This timer works perfectly in any piece of standalone code. However when I
set it from the routine that access the database, somehow the calls are
stacked and I do not see them occur until the end of the database access.

I initially suspected that the database I/O calls were occurring prior to
the timer event and that the I/O was blocking the event. However if I place
any type of debug statement in the code, the thing works. So now I am
wondering if it is caused by calling one timer event from a routine that was
launched from another timer event.

Is there anyway to force the order of event handling (on time - and without
putting message boxes in the code) so that it would work as you would
suspect based on code flow?

Thanks for any and all help/suggestions,
Paul Orman
pa********@comcast.net

Nov 21 '05 #1
Share this Question
Share on Google+
2 Replies


P: n/a
Its a bit unclear from your code exactly how you are handling these
events. You must first recognize that the Event Handling precedence and
architecture varies drastically from that of the VB6 model. When a
Timer raises and event to the form - the handling function is executed
by the Timer thread - NOT - by the form. Thus, the Timer is executing
the function in parallel with the form. This is highly problematic when
it comes to updating the Form Interface without first alerting the
Forms main GUI Thread that an update is about to occur. This is because
the resources used by the GUI thread are not thread safe, and therefore
should NEVER be updated by a seperate thread.

Also you need to make sure that 2 seperate threads are not attempting
to update the same variable at the same time. This is handled throw
using a Mutex.

Approprate Event Handling for a GUI interface with extra threads is
handled in the following model. Declare a variable for the timer event
delegate. And an assocated function that will handle the actual update
to the interface (which is the AddressOf for the delegate). This
function Doesnt directly handle the Elepsed event. Add another function
which handled the elapsed event from the timer. Remember - the Timer
Thread is executing this function *NOT* the main gui thread. So what
you want to do is tell the Main Gui Thread to execute the function that
actually updates the interface. This is done by the mybase.Invoke (or
begin invoke if you dont want the Timer thread to wait for the Main Gui
thread to handle the update).

Private _d_onEventElapsed as New
System.Timers.ElapsedEventHandler(AddressOf onTimerElapsed)
Private Sub __TimerElapsed(ByVal sender As Object, ByVal e As
System.Timers.ElapsedEventArgs) Handles t.Elapsed
Try
mybase.Invoke(_d_onEventElapsed, New Object() {sender, e})
Catch ex As Exception
#If DEBUG Then
Stop
#End If
End Try
End Sub
Private Sub onTimerElapsed(ByVal sender As Object, ByVal e As
System.Timers.ElapsedEventArgs)
Try
'UPDATE THE INTERFACE HERE - IT IS NOW EXECUTED BY THE MAIN
GUI THREAD
Catch ex As Exception
#If DEBUG Then
Stop
#End If
End Try
End Sub

Let me know if this helps, I can provide an example of a Threaded Data
object that the main gui requests the data to load, and the object
raises events when the query is complete. But, this example should get
you started down the correct path.

Kevin M. Schreiner
VP Software Architecture
Business Intelligence Force, Inc.

Nov 21 '05 #2

P: n/a
Thank you very much, after some testing this adequately explains what is
happening. I did not (and do not) understand the dotnet architecture (I
have some reading to do :-). I am assuming at this point based upon your
explanation and the behavior I am seeing that there is a single thread that
handles the timer events. To clarify the point I was unclear on ... I have
my main body of code (Form1) that has a timer. On the form load I start a
timer (Timer1). In the Handles Timer1.Tick function I call a sub
LoadFromDataBase(). This routine starts another timer (Timer2) that then
sets the label colors in the Handles Timer2.Tick function. So apparently I
have a Timer thread nested inside of another Timer thread (that is already
running). I believe what I am seeing happen is the second timer thread
being serviced *after* completion of the first (and original) timer event.
Based upon your explanation and what I am seeing occur, I do not believe
this is going to work for me (as I had intended) and I will need to rework
this with an altered solution. Thank you once again for your explanation.

Paul Orman
pa********@comcast.net

"kevin" <ke*************@gmail.com> wrote in message
news:11**********************@f14g2000cwb.googlegr oups.com...
Its a bit unclear from your code exactly how you are handling these
events. You must first recognize that the Event Handling precedence and
architecture varies drastically from that of the VB6 model. When a
Timer raises and event to the form - the handling function is executed
by the Timer thread - NOT - by the form. Thus, the Timer is executing
the function in parallel with the form. This is highly problematic when
it comes to updating the Form Interface without first alerting the
Forms main GUI Thread that an update is about to occur. This is because
the resources used by the GUI thread are not thread safe, and therefore
should NEVER be updated by a seperate thread.

Also you need to make sure that 2 seperate threads are not attempting
to update the same variable at the same time. This is handled throw
using a Mutex.

Approprate Event Handling for a GUI interface with extra threads is
handled in the following model. Declare a variable for the timer event
delegate. And an assocated function that will handle the actual update
to the interface (which is the AddressOf for the delegate). This
function Doesnt directly handle the Elepsed event. Add another function
which handled the elapsed event from the timer. Remember - the Timer
Thread is executing this function *NOT* the main gui thread. So what
you want to do is tell the Main Gui Thread to execute the function that
actually updates the interface. This is done by the mybase.Invoke (or
begin invoke if you dont want the Timer thread to wait for the Main Gui
thread to handle the update).

Private _d_onEventElapsed as New
System.Timers.ElapsedEventHandler(AddressOf onTimerElapsed)
Private Sub __TimerElapsed(ByVal sender As Object, ByVal e As
System.Timers.ElapsedEventArgs) Handles t.Elapsed
Try
mybase.Invoke(_d_onEventElapsed, New Object() {sender, e})
Catch ex As Exception
#If DEBUG Then
Stop
#End If
End Try
End Sub
Private Sub onTimerElapsed(ByVal sender As Object, ByVal e As
System.Timers.ElapsedEventArgs)
Try
'UPDATE THE INTERFACE HERE - IT IS NOW EXECUTED BY THE MAIN
GUI THREAD
Catch ex As Exception
#If DEBUG Then
Stop
#End If
End Try
End Sub

Let me know if this helps, I can provide an example of a Threaded Data
object that the main gui requests the data to load, and the object
raises events when the query is complete. But, this example should get
you started down the correct path.

Kevin M. Schreiner
VP Software Architecture
Business Intelligence Force, Inc.

Nov 21 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.