在C#中调用BeginRead()后关闭NetworkStream

时间:2011-08-17 13:52:20

标签: c# asynchronous networkstream

我已经实现了一个模拟串口的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()方法没有调用的事实有关。如果是这种情况,我怎么能在不崩溃的情况下关闭流?

1 个答案:

答案 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:对于生产代码,它需要一些异常处理等。