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

iso*_*rik 5 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());
Run Code Online (Sandbox Code Playgroud)

从另一个线程调用以下方法:

 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);
    }
Run Code Online (Sandbox Code Playgroud)

这似乎工作正常.我可以毫无问题地向网络上的设备发送和接收数据.但是,当我尝试使用以下方法断开连接时,程序崩溃:

public override void disconnect()
{
    server.Close();
}
Run Code Online (Sandbox Code Playgroud)

它会引发以下错误:

A first chance exception of type 'System.ObjectDisposedException' occurred in System.dll
Run Code Online (Sandbox Code Playgroud)

我也尝试过如下实现disconnect方法:

server.GetStream().Close();
Run Code Online (Sandbox Code Playgroud)

但这会导致以下错误:

A first chance exception of type 'System.InvalidOperationException' occurred in System.dll
Run Code Online (Sandbox Code Playgroud)

我假设这与调用BeginRead()方法并且EndRead()方法没有调用这一事实有关.如果是这种情况,我怎么能关闭流而不会崩溃?

Yah*_*hia 1

我只会调用GetStream一次并将结果存储在某处并使用它来访问流。

Stream nstrm = server.GetStream();
Run Code Online (Sandbox Code Playgroud)

用于nstrmNetworkStream...的所有访问

最安全的方法是维护一个用于关闭的标志,然后将该标志设置为disconnect().

在检查该标志DataReceived后,您将直接EndRead执行以下操作:

server.Close();
nstrm.Close();
Run Code Online (Sandbox Code Playgroud)

请参阅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);
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句:对于生产代码,它需要一些异常处理等。