Solved

AsyncCallback thread terminates and code does not return to main app

Posted on 2004-09-07
6
323 Views
Last Modified: 2008-01-09
Hi Experts,
Im writing an e-mail app in vb.net to receive specific e-mails and decode a hex attachment in the e-mail.
Originally i found an e-mail app for vb6 which works great (using winsock). so in my infinite wisdom decided to do the whole thing in vb.net.
I have written a class that creates a socket then uses the Async send and receive functions, whose events are picked up by corresponding delegates.
I get so far in the main app where i receive the first part of an e-mail, my OnDataArrival event is fired by the receive callback delegate, then half way through the code in the OnDataArrival function the  receive callback delegate takes back control and the code in rest of the  OnDataArrival function does not execute and program flow ceases.
Now I have seen in examples that you can use the ManualResetEvent to stop the thread but this does not seem to help.

Here is the class

Public Class vbnetsock
    Public Event OnDataArrival(ByVal Message As String)
    Public Shared allDone As New ManualResetEvent(False)
    Dim IPEP As IPEndPoint
    Dim IPHE As IPHostEntry
    Dim mySocket As Socket
    Dim ascii As New ASCIIEncoding
    Const bufferSize As Integer = 1024

    Public Sub Connect(ByVal host As String, ByVal port As Integer)

        allDone.Reset()
        IPHE = Dns.Resolve(host)
        IPEP = New IPEndPoint(IPHE.AddressList(0), 110)
        mySocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
        mySocket.BeginConnect(IPEP, New AsyncCallback(AddressOf Connect_Callback), mySocket)
        allDone.WaitOne()

    End Sub

    Private Sub Connect_Callback(ByVal ar As IAsyncResult)

        allDone.Set()
        mySocket = CType(ar.AsyncState, Socket)
        mySocket.EndConnect(ar)
        Dim buff(bufferSize) As Byte
        mySocket.BeginReceive(buff, 0, buff.Length, 0, New AsyncCallback(AddressOf Receive_CallBack), buff)

    End Sub

    Private Sub Receive_CallBack(ByVal ar As IAsyncResult)

        Dim bytes() As Byte = ar.AsyncState
        Dim numBytes As Int32 = mySocket.EndReceive(ar)
        'If numBytes > 0 Then
        ReDim Preserve bytes(numBytes - 1)
        Dim received As String = ascii.GetString(bytes)
        RaiseEvent OnDataArrival(received)

    End Sub

    Public Sub Send(ByVal message As String)

        Dim buff As Byte() = Encoding.ASCII.GetBytes(message)
        mySocket.BeginSend(buff, 0, buff.Length, SocketFlags.None, New AsyncCallback(AddressOf Send_CallBack), mySocket)

    End Sub

    Private Sub Send_CallBack(ByVal ar As IAsyncResult)

        mySocket = CType(ar.AsyncState, Socket)
        mySocket.EndSend(ar)
        Dim buff(bufferSize) As Byte
        mySocket.BeginReceive(buff, 0, buff.Length, 0, New AsyncCallback(AddressOf Receive_CallBack), buff)

    End Sub
    Public Sub close()

        mySocket.Close()

    End Sub

End Class

Please correct any prgramming foobars i have made as im still quite new to vb.net
Any help would be most appreciated.
0
Comment
Question by:Yrag1
  • 2
6 Comments
 
LVL 7

Expert Comment

by:vbwizardry
ID: 12002331
In your place I would use asynchronous event (call back). Also use a SyncLock in the events body that way it will force thread to wait for the previous one to complete.
Sub …_OnDataArrival(ByVal Message As String)
SyncLock Me
      ‘Your code here
End SyncLock
End Sub
Try it
0
 
LVL 1

Author Comment

by:Yrag1
ID: 12008592
I still does not work and ends in the same place.
What do you mean by "asynchronous event (call back) "?
0
 
LVL 7

Accepted Solution

by:
vbwizardry earned 400 total points
ID: 12019858
Try this code: I have changed it a litle.

Public Class VBNetSock
    Public Event OnDataArrival(ByVal Message As String)
    Private Shared allDone As New ManualResetEvent(False)
    Private mySocket As Socket
    Private Const bufferSize As Integer = 1024
    Private buffer(bufferSize) As Byte

    Public Sub Connect(ByVal host As String, ByVal port As Integer, Optional ByVal timeout As Integer = 0)

        allDone.Reset()
        mySocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
        Dim ep As IPEndPoint = New IPEndPoint(Dns.Resolve(host).AddressList(0), port)
        mySocket.BeginConnect(ep, New AsyncCallback(AddressOf Connect_Callback), mySocket)
        allDone.WaitOne(timeout, False)
    End Sub

    Private Sub Connect_Callback(ByVal ar As IAsyncResult)
        Try
            allDone.Set()
            Dim remote As Socket = ar.AsyncState
            remote.EndConnect(ar)
            remote.BeginReceive(buffer, 0, buffer.Length, 0, New AsyncCallback(AddressOf Receive_CallBack), remote)
        Catch ex As Exception
            Debug.WriteLine(ex.ToString())
        End Try
    End Sub

    Private Sub Receive_CallBack(ByVal ar As IAsyncResult)
        Try
            Dim remote As Socket = ar.AsyncState
            Dim rtVal As Int32 = remote.EndReceive(ar)
            RaiseEvent OnDataArrival(Encoding.ASCII.GetString(buffer, 0, rtVal))
        Catch ex As Exception
            Debug.WriteLine(ex.ToString())
        End Try
    End Sub

    Public Sub Send(ByVal message As String)
        Try
            If message.LastIndexOf(vbCrLf) <> message.Length - 2 Then
                message &= vbCrLf
            End If
            Dim buffer As Byte() = Encoding.ASCII.GetBytes(message)
            mySocket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, New AsyncCallback(AddressOf Send_CallBack), mySocket)
        Catch ex As Exception
            Debug.WriteLine(ex.ToString())
        End Try
    End Sub

    Private Sub Send_CallBack(ByVal ar As IAsyncResult)
        Try
            Dim client As Socket = ar.AsyncState
            client.EndSend(ar)
            client.BeginReceive(buffer, 0, buffer.Length, 0, New AsyncCallback(AddressOf Receive_CallBack), client)
        Catch ex As Exception
            Debug.WriteLine(ex.ToString())
        End Try
    End Sub

    Public Sub close()
        mySocket.Close()
    End Sub

End Class
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Creating an analog clock UserControl seems fairly straight forward.  It is, after all, essentially just a circle with several lines in it!  Two common approaches for rendering an analog clock typically involve either manually calculating points with…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now