I have implemented a system that mimics the DataReceived event of a serial port, whereby the reading of data from a TCPClient object's NetworkStream is triggered by using the BeginRead() method as follows:
TcpClient server = new TcpClient();
server.Connect(IPAddress.Parse(ip), 10001);
server.GetStream().BeginRead(buffer, 0, buffer.Length, new AsyncCallback(DataReceived), server.GetStream());
which calls the following method from another thread:
private void DataReceived(IAsyncResult result)
{
res = result;
server.GetStream().EndRead(result);
//append received data to the string buffer
stringBuffer += System.Text.ASCIIEncoding.ASCII.GetString(buffer);
//clear the byte array
Array.Clear(buffer, 0, buffer.Length);
//trigger the parser
waitHandle.Set();
server.GetStream().BeginRead(buffer, 0, buffer.Length, new AsyncCallback(DataReceived), buffer);
}
This appears to work correctly. I can send and receive data to a device on the network without issue. However, when I attempt to disconnect using the following method, the program crashes:
public override void disconnect()
{
server.Close();
}
It throws the following error:
A first chance exception of type 'System.ObjectDisposedException' occurred in System.dll
I have also tried implementing the disconnect method as follows:
server.GetStream().Close();
but this results in the following error:
A first chance exception of type 'System.InvalidOperationException' occurred in System.dll
I assume this has something to do with the fact that the BeginRead() method has been called and the EndRead() method has not. If that is the case how can I close the stream without it crashing?
I would call GetStream
just once and store the result somewhere and use that for accessing the stream.
Stream nstrm = server.GetStream();
Use nstrm
for all accesses to the NetworkStream
...
safest way would be to maintain a flag for closing down and just setting that flag in disconnect()
.
In DataReceived
you would directly after EndRead
check for that flag and if it is set do this:
server.Close();
nstrm.Close();
see http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.getstream.aspx
EDIT - as per comment:
if (flag2Close)
{
server.Close();
nstrm.Close();
flag2Close = false;
}
else
{
nstrm.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(DataReceived), buffer);
}
BTW: for production code it needs some exception handling etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With