我正在尝试从 NetworkStream 读取数据。我写下一个代码:
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
Problem:我创建新客户端和新流。通过使用BeginRead
据我了解,它开始在新线程中读取数据。因此,为了获取实时数据,我开始新的BeginRead
在......的最后DataProcessing
功能。但当我尝试断开连接时遇到问题(看看Btn_Disconnect5000_Click
function): 我尝试关闭流和客户端,但它仍然尝试读入DataProcessing
方法并对我说:
无法访问已处置的对象
(感谢 djv 的正确翻译!)。
所以我想我需要先停止线程但不知道如何做到这一点:我尝试过Dispose()
方法,先尝试关闭流,但仍然不行。我也尝试打电话EndRead
手动方法,但无法理解我必须分配给它作为参数(参数)的内容。
EndRead
实际上并没有停止异步读取。它获取读取的字节数,结束当前的读取操作并抛出操作期间可能发生的任何异常。因此调用它不会阻止进一步的异步操作发生。
我建议您在回调中插入一个空检查,这将退出该方法并停止BeginRead
以免被更多地召唤。
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
通过空检查后可能会被处置。
您应该在回调中检查流的原因是,正如我们所讨论的,在“关闭”TCP 连接后,它会进入CLOSE_WAIT
, TIME_WAIT
或其中之一FIN_*
状态,以便操作系统仍然可以将迟到/重传的数据包映射到它。
NetworkStream.BeginRead()
最终调用WSARecv https://msdn.microsoft.com/en-us/library/windows/desktop/ms741688(v=vs.85).aspx它在本机端注册一个异步操作,因此它不知道您的套接字是否已释放,因为它只关心连接是否处于活动状态(CLOSE_WAIT
and TIME_WAIT
对于操作系统来说,连接仍然被视为活动的)。即使套接字/流已释放,这也可能导致回调被调用。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)