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

.NET 4.8并行任务中实时读取含CR的进程标准输出问题

解决仅用CR回车符输出的进程实时读取问题(.NET 4.8)

原有的并行进程代码依赖OutputDataReceived事件读取输出,但这个事件只在检测到换行符(LF)时才触发。你的后台程序输出进度时只用回车符(CR)覆盖当前行(比如输出1%\r2%\r...),没有换行,导致事件无法实时触发,只能等进程结束后拿到最终结果。

下面是基于原有Task Factory方案修改后的代码,实现逐字符读取输出、实时响应CR更新UI进度:

Private Function Test_ParallelTasks(ByVal MediaToConvert As String, OutCtl As TextBox) As Integer
    Dim _processexitcode As Integer = -1
    Dim _CurrentProcess As Process = Nothing

    ' 启动后台任务处理进程
    Task.Factory.StartNew(Function()
        Dim psInfo As New ProcessStartInfo() With {
            .RedirectStandardOutput = True,
            .CreateNoWindow = True,
            .UseShellExecute = False,
            .FileName = "你的后台程序路径", ' 替换成你的后台程序
            .Arguments = MediaToConvert,
            .WindowStyle = ProcessWindowStyle.Hidden
        }

        _CurrentProcess = New Process() With {
            .StartInfo = psInfo,
            .EnableRaisingEvents = True,
            .SynchronizingObject = Me
        }

        ' 添加进程退出事件
        AddHandler _CurrentProcess.Exited, Sub(source As Object, ev As EventArgs)
            _processexitcode = _CurrentProcess.ExitCode
            Console.WriteLine("进程退出,代码: {0} 时间: {1}", _processexitcode, _CurrentProcess.ExitTime)
        End Sub

        _CurrentProcess.Start()

        ' 直接读取StandardOutput流,逐字符处理CR
        Dim outputBuffer As New StringBuilder()
        Dim reader As StreamReader = _CurrentProcess.StandardOutput
        Dim charRead As Integer
        Dim currentChar As Char

        While _CurrentProcess.HasExited = False
            charRead = reader.Read()
            If charRead = -1 Then
                ' 流暂时无数据,等待10ms避免空循环占用CPU
                Thread.Sleep(10)
                Continue While
            End If

            currentChar = Convert.ToChar(charRead)
            If currentChar = vbCr Then ' 遇到回车符,更新UI并清空缓冲区
                Dim progressText As String = outputBuffer.ToString().Trim()
                If Not String.IsNullOrEmpty(progressText) Then
                    ' 调度到UI线程更新
                    Task.Factory.StartNew(Sub()
                        Try
                            ' 覆盖当前行:根据需求调整,比如直接替换文本
                            OutCtl.Text = progressText
                            ' 若需保留历史并覆盖当前行,可改用:
                            ' OutCtl.SelectionStart = 0
                            ' OutCtl.SelectionLength = OutCtl.Text.Length
                            ' OutCtl.SelectedText = progressText
                        Catch ex As Exception
                            ' 窗体关闭时可能抛出异常,忽略即可
                        End Try
                    End Sub, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.FromCurrentSynchronizationContext())
                End If
                outputBuffer.Clear()
            Else
                outputBuffer.Append(currentChar)
            End If
        End While

        ' 处理进程退出后剩余的输出
        If outputBuffer.Length > 0 Then
            Dim finalText As String = outputBuffer.ToString().Trim()
            Task.Factory.StartNew(Sub()
                Try
                    OutCtl.AppendText(finalText + Environment.NewLine)
                Catch ex As Exception
                End Try
            End Sub, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.FromCurrentSynchronizationContext())
        End If

        _CurrentProcess.Close()
        Return _processexitcode
    End Function, TaskCreationOptions.LongRunning, CancellationToken.None).Wait() ' 按需决定是否等待后台任务完成

    Return If(_processexitcode = 0, 1, 0)
End Function

关键修改说明

  • 放弃事件驱动读取:不再依赖BeginOutputReadLine(),改为直接读取StandardOutput流,逐字符解析,摆脱换行符限制。
  • 实时响应CR:遇到回车符(vbCr)立即更新UI并清空缓冲区,模拟后台程序覆盖当前行的行为。
  • UI线程安全:通过TaskScheduler.FromCurrentSynchronizationContext()确保UI更新在主线程执行,避免跨线程异常。
  • 优化循环效率:流无数据时短暂休眠,避免空循环占用过多CPU。
  • 收尾剩余输出:进程退出后,处理缓冲区中未触发CR的剩余内容。

注意事项

  • 若后台程序存在标准输出缓冲(部分程序会批量输出),可能导致CR无法实时传递,此时需修改后台程序禁用缓冲(比如C++程序用setbuf(stdout, NULL))。
  • 可根据需求调整UI更新逻辑,比如保留历史进度或仅显示当前百分比。

内容的提问来源于stack exchange,提问作者Dude named Ben

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 07:28:10