Raising Events using Threads in VB.NET


G

Guest

I'm currently trying to solve a problem that has evaded me for months now. I
am attempting to raise an event from a custom class that can be handled by
the main UI.

Here's an example of my class:
Imports System.Threading

Public Class ASyncTestObject
Private Delegate Sub ThreadEndDelegate(ByRef e As
ASyncTestObject.ASyncTestObjectEventArgs)
Private D As New ThreadEndDelegate(AddressOf OnThreadEnd)
Public Event ThreadEnd(ByVal sender As Object, ByVal e As
ASyncTestObjectEventArgs)
Private _W As Thread
Private _e As ASyncTestObjectEventArgs

Public Class ASyncTestObjectEventArgs
Inherits EventArgs
End Class

Private Delegate Sub Callback(ByVal e As IAsyncResult)

Protected Sub OnThreadEnd(ByRef e As ASyncTestObjectEventArgs)
Trace.WriteLine("Raising event from " & Thread.CurrentThread.Name)
_e = e
RaiseEvent ThreadEnd(Me, _e)
End Sub

Private Sub Work()
Trace.WriteLine("New ASyncObject working from " &
Thread.CurrentThread.Name)
_W.Sleep(5000)
D(New ASyncTestObjectEventArgs)
End Sub

Public Sub New()
Trace.WriteLine("New ASyncObject created by " &
Thread.CurrentThread.Name)
_W = New Thread(AddressOf Work)
_W.Name = "Worker Thread"
_e = New ASyncTestObjectEventArgs
End Sub

Public Sub StartWork()
Trace.WriteLine("New ASyncObject started on " &
Thread.CurrentThread.Name)
_W.Start()
End Sub
End Class

However, as I follow my code, the Trace.WriteLine method identifies that the
object is being called from the Worker Thread. As I handle the event in a
console application, the event is being handled on the Worker Thread instead
of the Main Thread.

Here's the example of my console application test:
Imports ASyncObject
Module Module1
Private WithEvents A As ASyncTestObject

Sub Main()
System.Threading.Thread.CurrentThread.Name = "Main Thread"
A = New ASyncTestObject
Console.WriteLine("Starting worker process...")
A.StartWork()
Console.WriteLine("Worker process working...")
Console.ReadLine()
End Sub

Private Sub A_Done(ByVal sender As Object, ByVal e As
ASyncTestObject.ASyncTestObjectEventArgs) Handles A.ThreadEnd
Trace.WriteLine("New ASyncObject.ThreadDone handled by " &
System.Threading.Thread.CurrentThread.Name)
Console.WriteLine("Worker process completed.")
End Sub

End Module

Any insights or resources would be welcome as I have struck out trying to
find resources on my own.

Thanks!
 
Ad

Advertisements

M

Mattias Sjögren

I'm not sure exactly what you're asking for since I don't see a
question in your message. But I assume you want the event handler to
run on your main thread. If you have a Winforms UI you can call
Control.Invoke to execute a delegate on the UI thread.



Mattias
 
D

Dick Grier

Hi,

If I understand your question, the statement that you made:
However, as I follow my code, the Trace.WriteLine method identifies that the
object is being called from the Worker Thread. As I handle the event in a
console application, the event is being handled on the Worker Thread instead
of the Main Thread.
<<

is enlightening. That's the way it is designed to work. Event code
executes in the thread context, not the context of the calling code. If you
need to have this execute in the calling code's thread context, you have to
call an Async Delegate from your worker thread (which normally only is
required if you are dealing with UI (STAThread), not a console app).

I hope this helps.

Dick

--
Richard Grier (Microsoft Visual Basic MVP)

See www.hardandsoftware.net for contact information.

Author of Visual Basic Programmer's Guide to Serial Communications, 4th
Edition ISBN 1-890422-28-2 (391 pages) published July 2004. See
www.mabry.com/vbpgser4 to order.
 
G

Guest

Yes, the question is how do I create a callback to raise an event on the main
thread? The class is a simple example of a much larger class I'm attempting
to develop currently that handles several asynchronous calls that the UI must
then respond to. I've searched for clear examples on this, but I can't seem
to find a good example.

Basically, I want the UI programmer to only have to worry about handling the
events of the class. I don't want them to know if they have to Invoke a
control. I can raise the event, the UI will catch it at times, but often with
unexpected behavior.

I would prefer their coding look more like:
Private Sub A_Done(ByVal sender as Object, ByVal e as EventArgs) Handles
A.Done
Label1.Text = "A is done."
End Sub

If I could just be pointed to some good discussions on threading, delegates
and events I would be greatful. I need examples of a class raising events to
be handled on a UI thread.

Thanks!
 
J

Jon Skeet [C# MVP]

CQuick said:
Yes, the question is how do I create a callback to raise an event on the main
thread?
You just make your event handler call Control.Invoke or
Control.BeginInvoke in exactly the same way as you would at other
times. This doesn't actually raise the event in the UI thread, but it
lets you whatever work you want done when the event is raised, doing
that work in the UI thread.
Basically, I want the UI programmer to only have to worry about handling the
events of the class. I don't want them to know if they have to Invoke a
control. I can raise the event, the UI will catch it at times, but often with
unexpected behavior.
In that case, you could change how you raise the event, calling
Control.Invoke/BeginInvoke *before* the event is raised, and then
raising the event from within the UI thread.
 
Ad

Advertisements

D

Dick Grier

Hi,

Jon has pointed you in the correct direction. You use Control.Invoke or
BeginInvoke to call a Delegate which transfers context to the STAThread (UI)
where the control lives. There are examples online.

Since this is a Delegate, not specifically an event, there is nothing
"built-in" to VB that generates the handler for you. So, you have to
provide it for your user -- and the normal way is to document it. However,
your class can provide the actual delegate, and you simply have to include a
property that the user of your class assigns to some reference object in the
UI that your delegate can use to handle the update correctly. This will
make it easier for your user -- but it still won't be completely
transparent; (s)he will have to do a small amount of work.

Ken Getz wrote an article for CoDe magazine (Jan/Feb 2004) that illustrates
what I'm talking about in the preceding paragraph. I believe that the
article may be found in the archives at www.code-magazine.com.

Dick

--
Richard Grier (Microsoft Visual Basic MVP)

See www.hardandsoftware.net for contact information.

Author of Visual Basic Programmer's Guide to Serial Communications, 4th
Edition ISBN 1-890422-28-2 (391 pages) published July 2004. See
www.mabry.com/vbpgser4 to order.
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top