Welcome Guest ( Log In | Register )



 
Reply to this topicStart new topic
> Help: Multi-threading Trouble In Custom Socket Component
turbopowerdmaxst...
post Aug 15 2007, 10:23 PM
Post #1


Premium Member
Group Icon

Group: [HOSTED]
Posts: 373
Joined: 16-February 06
From: Kolkata, India
Member No.: 11,322



I am creating a wrapper component for the System.Net.Sockets.Socket class which would resemble the Winsock control. The basic idea is to do operations such as Connect & Receive asynchronously. The component has events such as Connected, PacketArrival in response to these. To do this, I use the following code:-

Socket Code
CODE
Imports System.Net.Sockets

Public Class MySocket
    Dim Sck As Socket       ' Socket Object

    ' Connect Method
    Sub Connect(ByVal Host As String, ByVal Port As Integer)
        Sck = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)

        ' Connect Multithreaded
        Sck.BeginConnect(Host, Port, New AsyncCallback(AddressOf ConnectCallBack), Sck)
    End Sub

    ' CallBack For System.Net.Sockets.Socket's asynchronous Connect Operation
    Private Sub ConnectCallBack(ByVal ar As IAsyncResult)
        Sck.EndConnect(ar)
        RaiseEvent Connected()
    End Sub

    ' The event to Notify the Owner Form
    Public Event Connected()
End Class


The problem here is that the Connected event is raised on the thread of the asynchronous Connect method of the Socket. So, if I try to access any control from this event's handler, a Cross-thread operation not valid exception is generated.

Window Code
CODE
Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        mSck.Connect("www.microsoft.com", 80)
    End Sub

    Private Sub mSck_Connected() Handles mSck.Connected
        ' Set the Window Text to Notify this Event
        Me.Text = "Connected"
    End Sub

End Class


I am able to get past this by following the process stated in MSDN for making thread safe calls.
CODE
Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        mSck.Connect("www.microsoft.com", 80)
    End Sub

    Delegate Sub ConnectedCallBack()
    Private Sub mSck_Connected() Handles mSck.Connected
        Dim D As New ConnectedCallBack(AddressOf SocketConnected)
        Me.Invoke(D)
    End Sub

    Sub SocketConnected()
        ' Set the Window Text to Notify this Event
        Me.Text = "Connected"
    End Sub

End Class


While, this works, I am not satisfied with having to create callbacks for these routine events. Is there a way to raise the event in the same thread as that of the Form?
Go to the top of the page
 
+Quote Post
faulty.lee
post Aug 16 2007, 03:01 PM
Post #2


Premium Member
Group Icon

Group: [HOSTED]
Posts: 479
Joined: 5-November 06
Member No.: 17,016



QUOTE(turbopowerdmaxsteel @ Aug 16 2007, 06:23 AM) *
While, this works, I am not satisfied with having to create callbacks for these routine events. Is there a way to raise the event in the same thread as that of the Form?

I don't think you have much choices. I'm also trying to learn more about multithreading, I found that it's actually very tedious to do. I've written a multithreaded multimedia software, running from 5 to 20 threads at a time. Took me quite a while to find tricks that can synchronize them all. Also, sometime when it fail, it doesn't just stop, but it runs for a while, then start to show some funny behavior. So have to spend more time debugging.

Anyway, as for your case, i've done something similar as well, but i'm using a main tread to loop and wait for the event, and then dispatches the job to worker threads. The worker thread contained in a separated class. Called using a function, and that function will then create the thread to do the job. So, when i call the function, a new instance is instantiated, which everything contain within itself. To keep track of the worker thread, you can add that into an array. Then have the main thread check for a bit that indicate if the job is done, then you can dispose and remove it from the array. The checking can be done at a preset duration, depending on the job load, or whenever a new worker thread need to be added.
Go to the top of the page
 
+Quote Post
turbopowerdmaxst...
post Aug 16 2007, 03:12 PM
Post #3


Premium Member
Group Icon

Group: [HOSTED]
Posts: 373
Joined: 16-February 06
From: Kolkata, India
Member No.: 11,322



I have manged to get the job done. What I did was inherit the class fron System.Windows.Forms.Control. This allows Invoke to be called from within the class and thus removes the overhead of having to do so everytime. This comes at a cost, though. The Socket control is no longer the design time only visible thingy. So, I had to handle the Paint messages for the control and it is now quite similar to the Winsock control.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic

Collapse

> Similar Topics

Topics Topics


 



- Lo-Fi Version Time is now: 7th September 2008 - 10:35 PM