I've been having difficulty in making cross-thread calls to my
controls on windows forms. Here's what I'm trying to do:

I have made a class, its purpose is to create a Socket and communicate
with a server, download some information and return it to my WinForm.
This socket performs all tasks asynchronously. I have created events
in this class so that it reports all its activities. Since all socket
communications are asynchronously, obviously this project becomes
multi-threaded.

Whenever I raise an event from inside an asynchronous callback, it
gives error that my controls require to be invoked first.
Here is my sample code: (its inaccurate, just try to get the idea)

--[Class1]--
Public Event ReportStatus([Text] As String)

Public Sub Connect()
    Dim mySocket = New Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp)
    RaiseEvent ReportStatus("Connecting to server...")
    mySocket.BeginConnect(HostName, Port, New AsyncCallback(AddressOf
ConnectCallBack), mySocket)
End Sub

Private Sub ConnectCallBack(ByVal ar As IAsyncResult)
    Try
        mySocket.EndConnect(ar)
        RaiseEvent ReportStatus("Connected!")

    Catch ex As SocketException
        RaiseEvent ReportStatus ("Could not connect: " & ex.Message)
    End Try
End Sub

--[Form1]--
Dim WithEvents MyClass as Class1

Private Sub ButtonClick (...) Handles ....
    MyClass = New Class1
    Class1.Connect()
End Sub

Private Sub MyClass_ReportStatus(Text as string) Handles
MyClass.ReportStatus
    Textbox1.Text = Text
End Sub


Now if you notice ReportStatus event in Form1... It sets the Text
property of the textbox. This event is called twice in the above code.
Once from the class's Connect sub. This is ok, it calls the event
properly and textbox's property is also updated ok.

But when this event is triggered for the second time, i.e. from the
async callback (ConnectCallBack in Class1), this becomes a cross-
thread call. That is because ConnectCallBack is a new thread created
by BeginConnect method in the Connect procedure.

To handle this simple problem, MSDN suggests that the textbox's
InvokeRequired property be checked first and then a delegated sub be
invoked to access the textbox's properties on the same thread. (http://
msdn.microsoft.com/en-us/library/ms171728.aspx)

My problem is that I have plenty of events to be called from cross
threads i.e. async callbacks, and I have plenty of controls on my
winform whose properties are to be updated. I can't write a separate
delegate sub for every control's invokerequired. Its going to create
excessive coding to achieve just little thing.

I am looking for a way that helps me the way events are raised. I want
that when my event is raised inside the async callback.. it should
become thread-safe then and there. I dont want to do coding inside my
winform to make events threadsafe. Is there a way to write events in
such a way that all RaiseEvents are already thread-safe when called
from the Class, and i dont have to write delegate sub for every event
call in my winform?

I hope you understand my gibberish in the last paragraph!


Regards
Faraz Azhar

Reply via email to