I
Ian Mac
I previously posted this in the VB.General forum, but thought that
this one might be a better place for it...sorry about the double post.
I have created a simple form with code that looks like this:
'******************************************************************************************
Public Class FEventRaiser
Inherits System.Windows.Forms.Form
Event MyEvent(ByVal eventName as string)
Private Delegate Sub EventRaiserDelegate(ByVal eventName As String)
Public Sub New()
...other code removed for clarity.
'Force the creation of the form's handle.
While Not IsHandleCreated
Dim temp As IntPtr = Handle
End While
End Sub
Public Sub RaiseAnEvent(ByVal eventName As String)
If Me.InvokeRequired Then
'Call made on thread different from the thread this form was
created on...BeginInvoke.
Me.BeginInvoke(New EventRaiserDelegate(AddressOf
RaiseAnEvent), New
Object() {eventName})
Else
'Call made on same thread as this form was created on...raise
the
event.
RaiseEvent MyEvent(eventName)
End If
End Sub
End Class
'******************************************************************************************
If I create an instance of this form from within another form, and
then make
calls to 'MyRaiseEvent' from within a threaded timer, it works as I
would
expect:
Public Class Form1
Inherits System.Windows.Forms.Form
....
Private WithEvents mEventRaiser as FEventRaiser
Private WithEvents mTimer as System.Timers.Timer
...
mEventRaiser = New FEventRaiser
mTimer = New System.Timers.Timer(1000)
mTimer.Enabled = True
....
Private Sub mEventRaiser_MyEvent(ByVal eventName As String) Handles
mEventRaiser.MyEvent
'This event is handled on the same thread that this form's message
pump is
running on.
Debug.WriteLine("Event processed on thread: " &
AppDomain.GetCurrentThreadId)
End Sub
Private Sub mTimer_Elapsed(ByVal sender As Object, ByVal e As
System.Timers.ElapsedEventArgs) Handles mTimer.Elapsed
mEventRaiser.RaiseAnEvent("This Works")
End Sub
End Class
Even though the timer event handler is firing on different thread IDs
than
the main thread, the call to the mEventRaiser.RaiseAnEvent ends up
performing the necessary BeginInvoke, which results in mEventRaiser
raising
an event back on the main thread...this is the behaviour I would
expect (and
want).
If I then modify this code somewhat so that the mEventRaiser is
actually
created once in the timer event handler, then it all stops working
(please
ignore the hack method I used for instantiating the CEventRaiser
object...the real way it's done is in a worker thread created at the
same
time the threaded timer is created). Here's the new timer event
handler:
Private Sub mTimer_Elapsed(ByVal sender As Object, ByVal e As
System.Timers.ElapsedEventArgs) Handles mTimer.Elapsed
If mEventRaiser Is Nothing Then
'One-time creation of event raiser. It used to be created in the
main
thread, but now it's created in
'the context of the timer's first-time-firing thread.
mEventRaiser = New FEventRaiser
End If
'As before...ask event raiser to raise event. This no longer works.
The
BeginInvoke in the RaiseAnEvent call
'does nothing.
mEventRaiser.RaiseAnEvent("This doesn't Work")
End Sub
End Class
I hope you can makes sense of this code, and any insight you can
provide
would be greatly appreciated.
this one might be a better place for it...sorry about the double post.
I have created a simple form with code that looks like this:
'******************************************************************************************
Public Class FEventRaiser
Inherits System.Windows.Forms.Form
Event MyEvent(ByVal eventName as string)
Private Delegate Sub EventRaiserDelegate(ByVal eventName As String)
Public Sub New()
...other code removed for clarity.
'Force the creation of the form's handle.
While Not IsHandleCreated
Dim temp As IntPtr = Handle
End While
End Sub
Public Sub RaiseAnEvent(ByVal eventName As String)
If Me.InvokeRequired Then
'Call made on thread different from the thread this form was
created on...BeginInvoke.
Me.BeginInvoke(New EventRaiserDelegate(AddressOf
RaiseAnEvent), New
Object() {eventName})
Else
'Call made on same thread as this form was created on...raise
the
event.
RaiseEvent MyEvent(eventName)
End If
End Sub
End Class
'******************************************************************************************
If I create an instance of this form from within another form, and
then make
calls to 'MyRaiseEvent' from within a threaded timer, it works as I
would
expect:
Public Class Form1
Inherits System.Windows.Forms.Form
....
Private WithEvents mEventRaiser as FEventRaiser
Private WithEvents mTimer as System.Timers.Timer
...
mEventRaiser = New FEventRaiser
mTimer = New System.Timers.Timer(1000)
mTimer.Enabled = True
....
Private Sub mEventRaiser_MyEvent(ByVal eventName As String) Handles
mEventRaiser.MyEvent
'This event is handled on the same thread that this form's message
pump is
running on.
Debug.WriteLine("Event processed on thread: " &
AppDomain.GetCurrentThreadId)
End Sub
Private Sub mTimer_Elapsed(ByVal sender As Object, ByVal e As
System.Timers.ElapsedEventArgs) Handles mTimer.Elapsed
mEventRaiser.RaiseAnEvent("This Works")
End Sub
End Class
Even though the timer event handler is firing on different thread IDs
than
the main thread, the call to the mEventRaiser.RaiseAnEvent ends up
performing the necessary BeginInvoke, which results in mEventRaiser
raising
an event back on the main thread...this is the behaviour I would
expect (and
want).
If I then modify this code somewhat so that the mEventRaiser is
actually
created once in the timer event handler, then it all stops working
(please
ignore the hack method I used for instantiating the CEventRaiser
object...the real way it's done is in a worker thread created at the
same
time the threaded timer is created). Here's the new timer event
handler:
Private Sub mTimer_Elapsed(ByVal sender As Object, ByVal e As
System.Timers.ElapsedEventArgs) Handles mTimer.Elapsed
If mEventRaiser Is Nothing Then
'One-time creation of event raiser. It used to be created in the
main
thread, but now it's created in
'the context of the timer's first-time-firing thread.
mEventRaiser = New FEventRaiser
End If
'As before...ask event raiser to raise event. This no longer works.
The
BeginInvoke in the RaiseAnEvent call
'does nothing.
mEventRaiser.RaiseAnEvent("This doesn't Work")
End Sub
End Class
I hope you can makes sense of this code, and any insight you can
provide
would be greatly appreciated.