Reputation: 1377
I am using async sockets in my project.
When i calling Disconnect method in my class NotifyConnection ObjecDispoded exception arises. I realize that that happen becaouse socket.Close() method calls Dispose inside.
Have anyone idea how close socket in this situation ?
public void Disconnect()
{
try
{
lock (_syncRoot)
{
_clientSocket.Shutdown(SocketShutdown.Both);
_clientSocket.Close();
}
}
catch (SocketException ex)
{
OnSocketExeceptionThrowed(new EventArgs<SocketException>(ex));
NotificationAgentEm.LogExceptionToConsole(ex);
}
}
I expcect what EndReceive not called because socket.ShutDown closes socket receiving data..but EndReceive called after socket.ShutDown;socket.Close.
End exception throwed because socket not exist at this moment.
private void OnReceiveData(IAsyncResult ar)
{
try
{
TransferStateObject state = null;
lock(_syncRoot)
{
string message;
state = (TransferStateObject)ar.AsyncState;
// in this place exception throwed . client socket not exist becaouse it destroyed in disconnect method
int bytesRead = _clientSocket.EndReceive(ar);
keleton of how i using async sockets.
public void Connect(string host, int port)
{
if (host == null)
throw new NullReferenceException();
try
{
_clientSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
_clientSocket.Connect(host, port);
}
catch (Exception ex)
{
NotificationAgentEm.LogExceptionToConsole(ex);
throw;
}
}
public void Disconnect()
{
try
{
lock (_syncRoot)
{
_clientSocket.Shutdown(SocketShutdown.Both);
_clientSocket.Close();
}
}
catch (SocketException ex)
{
OnSocketExeceptionThrowed(new EventArgs<SocketException>(ex));
NotificationAgentEm.LogExceptionToConsole(ex);
}
}
public void StartListen()
{
if (_clientSocket == null)
{
throw new InvalidOperationException("No connection");
}
try
{
BeginReceive();
}
catch (SocketException ex)
{
NotificationAgentEm.LogExceptionToConsole(ex);
OnSocketExeceptionThrowed(new EventArgs<SocketException>(ex));
}
}
private void BeginReceive()
{
try
{
var receivedTranferObject = new TransferStateObject();
_clientSocket.BeginReceive(
receivedTranferObject.Buffer,
0,
TransferStateObject.BufferSize,
0,
new AsyncCallback(OnReceiveData),
receivedTranferObject);
}
catch(SocketException ex)
{
OnSocketExeceptionThrowed(new EventArgs<SocketException>(ex));
NotificationAgentEm.LogExceptionToConsole(ex);
}
}
private void OnReceiveData(IAsyncResult ar)
{
try
{
TransferStateObject state = null;
lock(_syncRoot)
{
string message;
state = (TransferStateObject)ar.AsyncState;
// in this place exception throwed . client socket not exist becaouse it destroyed in disconnect method
int bytesRead = _clientSocket.EndReceive(ar);
//bla bla bla
}
}
p.s sorry for my english
Upvotes: 0
Views: 368
Reputation: 4869
Regardless of my comment above I would restructure the Disconnect method:
try
{
lock (_syncRoot)
{
if ( null != _clientSocket )
{
_clientSocket.Shutdown(SocketShutdown.Both);
_clientSocket.Close();
_clientSocket = null;
}
}
}
catch (SocketException ex)
...
So you do not shutdown/ close the socket a second time around.
But again, to really help you we would need more details on the main workflow.
hth
PS: I do know about the penalty of having the if inside the lock, but I wanted to keep it simple,
Mario
EDIT: I added the function after the discussion in the comments section:
private void OnReceiveData(IAsyncResult ar)
{
if ( null != _clientSocket )
{
try
{
TransferStateObject state = null;
lock(_syncRoot)
{
string message;
state = (TransferStateObject)ar.AsyncState;
int bytesRead = _clientSocket.EndReceive(ar);
//bla bla bla
}
}
}
else
{
//socket has been closed/ is closing
}
}
hth
Mario
Upvotes: 1