2

In my code I will run a process and retrieve part of the standard error output (a number) to raise an event which send a progress number.

Sometimes I have an exception at this line at ".First" method 'cause the string has nothing to split:

out = mp3gain_For_NonTag.StandardError.ReadLine.Trim.Split("%").First

The problem Is I want to add the necessary check to avoid that exception without doing a Try/Catch because in my speed tests I've noticed that a try/catch in this procedure will slow the performance a lot.

I want to simplify the code doing the necessary checks but without a catching any exception (By the moment the checks I've added would be executed quickly than a try/catch).

Here is the code:

Private Shared Sub Run_MP3Gain_NotTag()

    mp3gain_For_NonTag.Start() ' Run process

    Dim out as string  = mp3gain_For_NonTag.StandardError.ReadToEnd

    While Not mp3gain_For_NonTag.HasExited

        If Not String.IsNullOrEmpty(out) Then
            ' This would generate numbers between 1 to 100
            out = mp3gain_For_NonTag.StandardError.ReadLine.Trim.Split("%").First
        End If

        If Integer.TryParse(out, 0) Then
            RaiseEvent MP3Gain_Progress(out)
        End If

    End While

    RaiseEvent MP3Gain_Exited()

End Sub

...And for additional information, this is a sample of what I don't want to do, I can say that adding a try catch like in this modificated code code even without catching any exception kind this will reduce the performance a lot:

Private Shared Sub Run_MP3Gain_NotTag()

    mp3gain_For_NonTag.Start() ' Run process

    Dim out as string = mp3gain_For_NonTag.StandardError.ReadToEnd 

    While Not mp3gain_For_NonTag.HasExited

        Try
            out = mp3gain_For_NonTag.StandardError.ReadLine.Trim.Split("%").First
            RaiseEvent MP3Gain_Progress(out)
        Catch : End Try

    End While

    RaiseEvent MP3Gain_Exited()

End Sub
4

5 回答 5

2

我认为.FirstOrDefault()可能是您的答案。

又看了一眼。我不认为你的问题是第一种方法。First 抛出的异常是一种症状。您的问题是您out通过读取到流的末尾来设置,然后您通过尝试读取另一行来运行拆分,这将不会返回任何内容,因此会出现异常。只是拆分out,一切都应该没问题:

Dim out as string  = mp3gain_For_NonTag.StandardError.ReadToEnd

While Not mp3gain_For_NonTag.HasExited

    If Not String.IsNullOrEmpty(out) Then
        ' This would generate numbers between 1 to 100
        out = out.Trim.Split("%").First()
    End If
于 2013-10-09T20:15:48.513 回答
1

将结果粘贴ReadLine到另一个变量中并对其运行 String.IsNullOrEmpty(),然后对其进行修剪,对其运行 String.IsNullOrEmpty()。如果您仍然可以,请将其拆分并执行 First 操作。没有错误并且比你让它出错并抓住它更快。

Dim x as string = mp3gain_For_NonTag.StandardError.ReadLine
if Not String.IsNullOrEmpty(x) then
 x = x.trim
 If Not String.IsNullOrEmpty(x) then
  out = x.Split("%").First
 End If
End If
于 2013-10-09T20:17:10.610 回答
1

Try/Catch 块本身不会损害性能;只有当异常被实际抛出并捕获时,性能才会受到影响。

话虽如此,如果您可以完全避免使用异常,那么您当然应该这样做。在这种情况下,您可以轻松检查 的结果Split是否至少包含一个元素:

Dim parts = out = mp3gain_For_NonTag.StandardError.ReadLine.Trim.Split("%")
If parts.Length > 0 Then
    out = parts.First
End If

另一种选择是使用FirstOrDefault而不是First; Nothing如果没有结果,它将返回。

于 2013-10-09T20:17:20.910 回答
1

检查分割字符 ( %) 的索引,如果找到则只进行分割,如下所示:

If out.IndexOf("%") > -1 Then
    ' Do split logic here
End If
于 2013-10-09T20:16:48.033 回答
1

尝试使用检查“%”值的错误消息并返回适当值的函数。

out = ParseError(mp3gain_For_NonTag.StandardError.ReadLine.Trim())

Private Function ParseError(msg As String) As String
    Dim retVal As String = msg
    If msg.Contains("%") Then retVal = msg.Split("%").First
    Return retVal
End Function
于 2013-10-09T20:16:56.770 回答