You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

客户端服务器程序中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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 03:05:27