I have an application that is using asynchronous sockets with the begin/end design pattern.
Whenever I receive a new connection I create an object and store it in a collection. This object also stores the socket connection within itself and will be passed along in the begin methods “object state”.
Now that the server is running asynchronously, sending, receiving etc, there are multiple code paths executing at any given time for an object.
What I do not understand is:
If I call a function passing in my current object and in another thread, that object was just disposed, what happens to the other object that is currently inside executing code.
EDIT:
ex.)If you look at ReadDataCallback() where it is calling doSomthing(). If it is about to call doSomthing() with my “device” object, but the corresponding device had an exception in the SendCallback(). What state is the device object in that is just about to call doSomthing()?
Here is a code example.
void waitForData(MyDevice device)
{
try
{
if (device.SocketState.IsSSL)
{
device.SocketState.sslStream.BeginRead(device.SocketState.DataBuffer, 0, device.SocketState.DataBuffer.Length, m_readDataCallback, device);
}
else
{
device.SocketState.DeviceSocket.BeginReceive(device.SocketState.DataBuffer, 0, device.SocketState.DataBuffer.Length, SocketFlags.None, m_readDataCallback, device);
}
}
catch (SocketException se)
{
DisconnectAndRemove(device);
}
}
public void ReadDataCallback(IAsyncResult ar)
{
MyDevice device = (MyDevice)ar.AsyncState;
try
{
Queue<kustompacket> qps = null;
int iRx = 0;
if (device.SocketState.IsSSL)
{
iRx = device.SocketState.sslStream.EndRead(ar);
if (iRx == 0)
{
DisconnectAndRemove(device);
}
else if (iRx > 0)
{
device.CircularBuff.Add(iRx, device.SocketState.DataBuffer);
qps = device.CircularBuff.ReadPackets();
doSomthing(device);
}
}
else
{
if (device.SocketState.DeviceSocket != null)
{
if (device.SocketState.DeviceSocket.Connected)
{
// Read data from the client socket.
iRx = device.SocketState.DeviceSocket.EndReceive(ar);
if (iRx == 0)
{
DisconnectAndRemove(device);
}
else if (iRx > 0)
{
device.CircularBuff.Add(iRx, device.SocketState.DataBuffer);
qps = device.CircularBuff.ReadEncryptedPackets(device.SocketState.SessionID);
doSomthing(device);
}
}
}
}
if (qps != null)
{
MyDelegate meh = new MyDelegate(HandleDataReceived);
meh.BeginInvoke(device, qps, null, null);
}
if (iRx != 0)
{
waitForData(device);
}
}
catch (ObjectDisposedException ode)
{
//Socket has been closed
//DisconnectAndRemove(device);
}
catch (SocketException se)
{
//if (se.ErrorCode == 10054) // Error code for Connection reset by peer
//{
DisconnectAndRemove(device);
//}
}
catch (Exception ex)
{
DisconnectAndRemove(device);
}
}
public void SendCallback(IAsyncResult ar)
{
MyDevice device = (MyDevice)ar.AsyncState;
try
{
// Complete sending the data to the remote device.
if (device.SocketState.IsSSL)
{
device.SocketState.sslStream.EndWrite(ar);
}
else
{
int bytesSent = device.SocketState.DeviceSocket.EndSend(ar);
}
device.ResetAge();
}
catch (SocketException se)
{
DisconnectAndRemove(device);
}
catch (Exception ex)
{
}
if (device.SocketState.IsSSL)
{
device.Write();
}
}
If an object is disposed on one thread, it is disposed on all threads. If you do anything with it after the other thread disposes it, it should (but is not guaranteed to) throw an ObjectDisposedException.
http://msdn.microsoft.com/en-us/library/system.objectdisposedexception.aspx
If you are disposing an object on a thread while another thread may be expecting to work with it, you are doing something wrong. Consider controlling life time of the object on a single thread in a deterministic way.