如何停止从NetworkStream读取? [英] How to stop reading from NetworkStream?

查看:218
本文介绍了如何停止从NetworkStream读取?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从NetworkStream中读取数据。我写下一个代码:

I'm trying to read data from NetworkStream. I write next code:

Imports System.Net
Imports System.Net.Sockets

Public Class Form1
    Dim tcpclnt1 As New TcpClient
    Dim streamTcp1 As NetworkStream
    Dim DataBuffer(1024) As Byte    'Buffer for reading
    Dim numberOfBytes As Integer
    ' event for reading data from stream
    Dim evtDataArrival As New AsyncCallback(AddressOf DataProcessing) 

    Private Sub Btn_Connect5000_Click(sender As Object, e As EventArgs)_
            Handles Btn_Connect5000.Click
        ' Connecting to server
        tcpclnt1 = New TcpClient   
        tcpclnt1.Connect("192.168.1.177", 5000)
        streamTcp1 = tcpclnt1.GetStream()   'Create stream for current tcpClient
        ' HERE WE START TO READ
        streamTcp1.BeginRead(DataBuffer, 0, DataBuffer.Length, evtDataArrival, Nothing) 

    End Sub

    Public Sub DataProcessing(ByVal dr As IAsyncResult)
        numberOfBytes = streamTcp1.EndRead(dr) 'END READ
        ' ...HERE SOME ROUTINE FOR PRINT DATA TO TEXTBOXES...
        'START NEW READING 
        streamTcp1.BeginRead(DataBuffer, 0, DataBuffer.Length, evtDataArrival, Nothing)
    End Sub

    Private Sub Btn_Disconnect5000_Click(sender As Object, e As EventArgs)_
            Handles Btn_Disconnect5000.Click
        ' Disconnect from port 5000. Close TcpClient
        streamTcp1.Dispose()
        streamTcp1.EndRead(Nothing) 'And here mistake appears !!!
        streamTcp1.Close()
        tcpclnt1.Close()
    End Sub
End Class

问题:我创建新客户端和新流。通过使用 BeginRead ,据我所知,它开始在新线程中读取数据。所以为了实时数据,我在 DataProcessing 函数的末尾开始新的 BeginRead 。但我在尝试断开连接时遇到问题(查看 Btn_Disconnect5000_Click 函数):我尝试关闭流和客户端但是它会尝试读入 DataProcessing 方法并告诉我:

Problem: I create new client and new stream. By using BeginRead as I understand it starts to read data in new thread. So to do it for real time data, I start new BeginRead at the end of DataProcessing function. But I face the problem when try to disconnect (look at Btn_Disconnect5000_Click function): I try to close stream and client but it sill try to read in DataProcessing method and says me:


无法访问已处置的对象

Cannot access a disposed object

(感谢djv正确翻译!)。

(Thanks to djv for correct translation!).

所以我想我需要先停止线程但不能弄清楚如何做到这一点:我试过 Dispose()方法,先尝试关闭流,但仍然不能。我也尝试手动调用 EndRead 方法,但无法理解我必须将其作为参数(参数)分配给它。

So I suppose I need to stop thread first but can't figure out how to do this: I tried Dispose() method, tried close stream first but still can't. Also I tried to call EndRead method manually, but can't understand what I have to assign to it as argument (parameter).

推荐答案

EndRead 实际上并没有停止异步读取。它获取读取的字节数,结束 当前 读取操作,并抛出操作期间可能发生的任何异常。因此调用它不会阻止进一步的异步操作发生。

EndRead does not actually stop the asynchronous reading. It gets the amount of bytes read, ends the current read operation and throws any exceptions that might have occurred during the operation. Thus calling it will not stop further async operations from happening.

我建议你在回调中插入一个空检查,而不是退出方法并停止 BeginRead 被调用甚至更多。

I suggest you insert a null check in the callback instead which will exit the method and stop BeginRead from being called even more.

Public Sub DataProcessing(ByVal dr As IAsyncResult)
    If streamTcp1 Is Nothing Then _
        Return 'Stream is disposed, stop any further reading.

    numberOfBytes = streamTcp1.EndRead(dr)

正如the_lotus所说,你可能会还需要添加异常处理,因为如果你运气不够, streamTcp1 可能会在通过空检查后被处理掉。

As the_lotus says you might also need to add exception handling, because if you are unlucky enough streamTcp1 might get disposed after passing the null check.

你应该在回调中检查流的原因是,正如我们所讨论的那样,在关闭TCP连接之后,它进入 CLOSE_WAIT TIME_WAIT 或其中一个 FIN _ * 表明操作系统仍然可以将延迟/重传的数据包映射到它。

The reason why you should check the stream in the callback is because, as we discussed, after "closing" a TCP connection it enters CLOSE_WAIT, TIME_WAIT or one of the FIN_* states so that the OS can still map late/retransmitted packets to it.

NetworkStream.BeginRead()最终调用 WSARecv ,它注册一个异步操作本机端,因此它不知道您的套接字是否被处置,因为所有它关心的是连接是否处于活动状态( CLOSE_WAIT TIME_WAIT 连接仍被认为是OS的活动状态)。即使套接字/流被释放,这也可能导致调用回调。

NetworkStream.BeginRead() ultimately calls WSARecv which registers an asynchronous operation on the native side, thus it is not aware if your socket is disposed or not because all it cares about is if the connection is active (CLOSE_WAIT and TIME_WAIT connections are still considered active to the OS). This may cause the callback to be called even if the socket/stream is disposed.

这篇关于如何停止从NetworkStream读取?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆