Link to home
Start Free TrialLog in
Avatar of Iamtehbest
Iamtehbest

asked on

Async TCPIP, with ObjectDisposedException

I am having an issue with a bug in my program.  What's happening is that I get a:
A first chance exception of type 'System.ObjectDisposedException' occured in system.dll.  Problem is that sometimes this exception although user handled, will halt my program.  I understand what the error means.  What I don't understand is why it's happening in this code.  I would give you line numbers of where the error is happening, unfortunately the program halts at any line in this code that references the Socket.  Not all the time... but enough to make me annoyed.

I've read some threads suggesting other people to make a Disposed property.   Unfortunately, I know that can't work for me.  I think what's going on in my project is that the Async Method of reading the tcp stream is triggering 2 or more threads and they are all processing the data via this sub routine listed below.

If Thread #1 Processes all the data that it got from the tcp stream and determine it's time to close the socket, it closes it.

Meanwhile, Thread #2 went through all the condition checking to make sure the connection was open, it passed all the way through.  But as soon as it wants to start reading the actual data, it gets a Disposed Error...  because thread #1 closed the socket on it.

Any suggestions?  I really want to use Async since I am handling 600 connections right now.

The code is here below:
 
Imports System.Net.Sockets
Imports System.Text
Imports System.Threading
Public Class myStateObject
    ' Client  socket.
    Public workSocket As Socket = Nothing
    ' Size of receive buffer.
    Public Const BufferSize As Integer = 10024
    ' Receive buffer.
    Public buffer(BufferSize) As Byte
    ' Received data string.
    Public sb As New StringBuilder
    Public Server As Integer
    Public Channel As Integer
    Public ChannelType As Integer
End Class 'StateObject


    Public XSockets(200) As Socket

    Public ParentServer As Servers

Public Sub IncomingAGIData(ByVal dr As IAsyncResult)
        Dim dt As System.DateTime = System.DateTime.Now
        Dim myCompleteMessage As String = String.Empty
        Dim state As StateObject = CType(dr.AsyncState, StateObject)
        Dim NewState As StateObject
        Dim handler As Socket = state.workSocket

        If handler.Connected Then
            Dim bytesRead As Integer = handler.EndReceive(dr)
            If bytesRead > 0 Then
                state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead))
                myCompleteMessage = state.sb.ToString()
                If InStr(myCompleteMessage, "dead channel") Then

                    If state.ChannelType = 1 Then XSockets(state.Channel).Close()
                    'handler.Close()
                    Exit Sub
                End If
                If XSockets(state.Channel).Connected Then
                    If handler.Available = 0 Then
                        Try
                            NewState = New StateObject
                            NewState.workSocket = handler
                            NewState.Server = state.Server
                            NewState.Channel = state.Channel
                            NewState.ChannelType = state.ChannelType
                            If XSockets(state.Channel).Connected Then

                                If handler.Connected Then
                                    Try
                                        handler.BeginReceive(NewState.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf IncomingAGIData), NewState)
                                    Catch Ex As Exception
                                    End Try
                                End If

                            End If

                        Catch Ex As Exception
                            If state.ChannelType = 1 Then XSockets(state.Channel).Close()
                            handler.Close()
                            Exit Sub
                        End Try
                    Else
                        Try
                            NewState = New StateObject
                            NewState.workSocket = handler
                            NewState.Server = state.Server
                            NewState.Channel = state.Channel
                            NewState.ChannelType = state.ChannelType
                            If XSockets(state.Channel).Connected Then
                                If handler.Connected Then
                                    handler.BeginReceive(NewState.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf IncomingAGIData), NewState)
                                End If
                            End If

                        Catch Ex As Exception
                            If state.ChannelType = 1 Then XSockets(state.Channel).Close()
                            Exit Sub
                        End Try
                    End If
                End If
            Else
            End If
        Else
            If state.ChannelType = 1 Then XSockets(state.Channel).Close()
            handler.Close()
        End If
    End Sub

Open in new window

Avatar of bansidhar
bansidhar
Flag of India image

you have to use a try .. catch for the read as there is chance that the socket getting closed by another process. Also you must do a synclock for the read or 2 threads can read the data simultaneously and there is a chance that you receive incorrect data.

hope this helps  
ASKER CERTIFIED SOLUTION
Avatar of Iamtehbest
Iamtehbest

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Iamtehbest
Iamtehbest

ASKER

Figured it out myself.