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

发布于 2024-11-29 19:16:51 字数 1438 浏览 1 评论 0 原文

我已经实现了一个模仿串行端口的 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

我还尝试按如下方式实现断开连接方法:

server.GetStream().Close();

但这会导致以下错误:

A first chance exception of type 'System.InvalidOperationException' occurred in System.dll

我认为这与事实上,BeginRead() 方法已被调用,而 EndRead() 方法尚未调用。如果是这种情况,我怎样才能关闭流而不崩溃?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

浅黛梨妆こ 2024-12-06 19:16:51

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

Stream nstrm = server.GetStream();

NetworkStream 的所有访问都使用 nstrm...

最安全的方法是维护一个用于关闭的标志,然后在 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);
}

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文