我已经实现了一个模拟串口的DataReceived事件的系统,从而使用BeginRead()方法触发从TCPClient对象的NetworkStream读取数据,如下所示:
TcpClient server = new TcpClient();
server.Connect(IPAddress.Parse(ip), 10001);
server.GetStream().BeginRead(buffer, 0, buffer.Length, new AsyncCallback(DataReceived), server.GetStream());
从另一个线程调用以下方法:
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);
}
这似乎可以正常工作。我可以毫无问题地向网络上的设备发送和接收数据。但是,当我尝试使用以下方法断开连接时,程序崩溃:
public override void disconnect()
{
server.Close();
}
它会抛出以下错误:
A first chance exception of type 'System.ObjectDisposedException' occurred in System.dll
我也尝试过如下实现disconnect方法:
server.GetStream().Close();
但这会导致以下错误:
A first chance exception of type 'System.InvalidOperationException' occurred in System.dll
我认为这与调用BeginRead()方法并且EndRead()方法没有调用的事实有关。如果是这种情况,我怎么能在不崩溃的情况下关闭流?
答案 0 :(得分:1)
我只会调用GetStream
一次并将结果存储在某处并使用它来访问流。
Stream nstrm = server.GetStream();
使用nstrm
进行NetworkStream
...
最安全的方法是维持一个关闭标志,并在disconnect()
中设置该标志。
在DataReceived
中,您会在EndRead
之后直接检查该标志,如果已设置,请执行以下操作:
server.Close();
nstrm.Close();
请参阅http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.getstream.aspx
编辑 - 根据评论:
if (flag2Close)
{
server.Close();
nstrm.Close();
flag2Close = false;
}
else
{
nstrm.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(DataReceived), buffer);
}
BTW:对于生产代码,它需要一些异常处理等。