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

VB.Net函数阻塞UI求助:需保留UI操作权限以终止任务

问题分析与解决方案

你的代码核心问题在于线程和异步逻辑混用导致的混乱,加上缺少任务取消机制,具体问题包括:

  • 手动创建Thread后,内部调用Task.WhenAll却没有Await,线程会提前结束,异步任务脱离控制
  • refreshRichTextBox里用Task.Run包裹Invoke完全多余,Invoke本身就是切换回UI线程,多此一举反而增加开销
  • 所有行的处理任务并行执行,短时间内大量UI更新请求可能导致UI线程阻塞
  • 没有提供任务终止的入口,无法中途停止处理

修正后的代码

首先在窗体类里定义一个取消令牌源:

Private cts As CancellationTokenSource

然后重写按钮点击事件和相关方法:

Private Async Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    ' 先停止之前的任务(如果有的话)
    cts?.Cancel()
    cts?.Dispose()
    cts = New CancellationTokenSource()

    Try
        ' 初始化日志分隔线
        AppendToRichTextBox(RichTextBox1, vbCrLf & "======================================================")
        
        ' 拆分GCode行,过滤空行
        Dim GCODES As String() = GCode.Split({vbCrLf}, StringSplitOptions.RemoveEmptyEntries)
        
        ' 逐行异步处理(如果需要并行,可限制并发数,比如用SemaphoreSlim)
        For Each line In GCODES
            ' 检查是否取消
            cts.Token.ThrowIfCancellationRequested()
            
            ' 处理单行(后续可加入SerialPort发送逻辑)
            Await ProcessLineAsync(line)
            
            ' 可选:如果需要控制处理速度,加个延迟
            ' Await Task.Delay(100, cts.Token)
        Next
    Catch ex As OperationCanceledException
        AppendToRichTextBox(RichTextBox1, vbCrLf & "任务已终止")
    Catch ex As Exception
        AppendToRichTextBox(RichTextBox1, vbCrLf & $"出错:{ex.Message}")
    Finally
        cts.Dispose()
        cts = Nothing
    End Try
End Sub

Private Async Function ProcessLineAsync(line As String) As Task
    ' 这里后续加入SerialPort发送逻辑,比如:
    ' Await serialPort.WriteLineAsync(line)
    
    ' 更新RichTextBox
    AppendToRichTextBox(RichTextBox1, line)
End Function

Private Sub AppendToRichTextBox(rtextBox As RichTextBox, str As String)
    ' 如果不在UI线程,切换过去
    If rtextBox.InvokeRequired Then
        rtextBox.Invoke(Sub() AppendToRichTextBox(rtextBox, str))
        Return
    End If
    
    rtextBox.AppendText(str & vbCrLf)
    rtextBox.SelectionStart = rtextBox.Text.Length
    rtextBox.ScrollToCaret()
End Sub

关键改进点

  • 使用CancellationTokenSource实现任务取消,点击按钮时会先终止之前的任务,再启动新任务
  • 去掉多余的Thread和嵌套异步逻辑,直接用Async/Await让UI线程保持响应
  • 逐行处理(如果需要并行,可添加SemaphoreSlim控制并发数,避免UI被大量更新请求阻塞)
  • 简化UI更新逻辑,仅在需要时才切换到UI线程

终止任务的实现

你可以添加一个“终止”按钮,点击时执行:

Private Sub ButtonCancel_Click(sender As Object, e As EventArgs) Handles ButtonCancel.Click
    cts?.Cancel()
End Sub

内容的提问来源于stack exchange,提问作者Fabian Q

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 09:55:09