客户端服务器程序中Form2加载后陷入无限循环问题求助
问题分析与修复方案
核心无限循环原因
你的getMessage方法里的For循环被强制改成了死循环:
For infiniteCounter = 1 To 2 Try infiniteCounter = 1 ' 每次循环都把计数器重置为1,永远无法到达循环终止条件2 ' ... 其他代码 Catch ' ... End Try Next
这行infiniteCounter = 1直接导致循环永远不会结束,是无限循环的直接诱因。
其他关键问题与修复
除了死循环,代码还有几个必须修正的问题:
1. 线程安全与全局变量风险
returndata是全局变量,后台线程和UI线程同时访问会引发线程安全问题,应该将读取到的数据作为参数传递给doOrder,而非依赖全局变量。
2. 字符串与数字的Case匹配错误
order是字符串类型,但Select Case里用了数字0、1、2,VB.NET的隐式转换可能导致匹配失败,需改为字符串常量"0"、"1"、"2"。
3. 未处理Read的返回值
serverStream.Read返回实际读取的字节数,直接用inStream.Length会把未填充的空字节转成字符串,导致后续处理出错,必须用返回值截取有效数据。
4. 未判断$是否存在
returndata.IndexOf("$")如果找不到$会抛出异常,需要先检查索引是否大于等于0再执行Substring。
5. Form关闭后的线程泄漏
Form1关闭后,后台线程仍在运行,会占用资源,需要在Form关闭时终止线程。
修改后的完整代码示例
' 定义线程变量为类级成员,方便后续终止 Private ctThread As Threading.Thread ' 启动线程的代码 ctThread = New Threading.Thread(AddressOf getMessage) ctThread.IsBackground = True ' 设置为后台线程,程序退出时自动终止 ctThread.Start() Private Sub getMessage() ' 用While循环替代错误的For循环,添加退出条件 While Not ctThread.ThreadState = Threading.ThreadState.AbortRequested Try serverStream = clientSocket.GetStream() Dim inStream(1024) As Byte Dim bytesRead As Integer = serverStream.Read(inStream, 0, inStream.Length) If bytesRead <= 0 Then ' 连接断开,退出循环 Exit While End If Dim rawData As String = System.Text.Encoding.UTF8.GetString(inStream, 0, bytesRead) ' 先判断$是否存在 Dim dollarIndex As Integer = rawData.IndexOf("$") If dollarIndex < 0 Then Continue While ' 无效数据,跳过 End If Dim returndata As String = rawData.Substring(0, dollarIndex) serverStream.Flush() If returndata <> "" Then ' 将数据作为参数传递给UI线程的方法 If Form2.InvokeRequired Then Form2.Invoke(New Action(Of String)(AddressOf doOrder), returndata) Else doOrder(returndata) End If End If Catch ex As Exception ' 不要在后台线程用MsgBox,会阻塞线程,建议写入日志 Console.WriteLine(ex.ToString) End Try End While End Sub ' 修改doOrder方法,接收参数 Sub doOrder(returndata As String) Dim order As String = Strings.Left(returndata, 1) Select Case order Case "0" MsgBox("该昵称已存在") Case "1" Form2.Show() Form2.Text = Form1.Text3.Text Form1.Close() Case "2" Form2.List1.Items.Add(Strings.Right(returndata, Len(returndata) - 1)) End Select End Sub ' 在Form1的FormClosing事件中终止线程 Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing If ctThread IsNot Nothing AndAlso ctThread.IsAlive Then ctThread.Abort() End If End Sub
额外注意事项
- 后台线程中不要使用
MsgBox,会导致线程阻塞,建议改用日志输出或UI线程的提示框。 clientSocket和serverStream需要确保在连接断开时正确释放资源,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Idan Azari
相关产品推荐
相关产品推荐

