System.OutOfMemoryException和使用StringBuilder的复杂化

时间:2017-06-20 13:12:17

标签: vb.net visual-studio-2010 stringbuilder

以下代码给出了System.OutOfMemoryException,我尝试在我的代码中使用StringBuilder来更改它,但我无法成功使用它。

任何人都可以告诉我使用StringBuilder的最佳方法是什么,而不是代码中字符串之间的多个连接?

Dim sReport As String = ""
For i As Integer = 1 To oPuntInterpretar.Dies.Count

    ' DGARCIA: Per MeteoPlay3 no ens interessa que hi hagi diferència en l'hora local UTC, 
    '          ja que cada previsió s'ofereix des del mateir punt evaluat.
    oPuntInterpretar.DifHoraLocalUTC = 0

    If (oConfiguracio.Opcions_Meteo3D.LogPGs = True) Then
        ' Dades del report...
        sReport = "ID_PUNTGEOGRAFIC;" & oPuntInterpretar.IPuntGeografic & vbCrLf & _
                  "LATITUD_PUNTGEOGRAFIC;" & Math.Round(oPuntInterpretar.Latitud, 2) & vbCrLf & _
                  "LONGITUD_PUNTGEOGRAFIC;" & Math.Round(oPuntInterpretar.Longitud, 2) & vbCrLf & _
                  "ALCADA_PUNTGEOGRAFIC (metres);" & oPuntInterpretar.Alçada & vbCrLf & _
                  "TIPUS_PUNTGEOGRAFIC;" & IIf(oPuntInterpretar.Tipus = clsPuntGeografic.TipusPunt.Poblacio, "POBLACIO", "MUNTANYA") & vbCrLf & _
                  "DIF_HORALOCAL_UTC;" & oPuntInterpretar.DifHoraLocalUTC & vbCrLf & _
                  "DATA_MODEL;" & dtDataElaboracio.ToString & vbCrLf & _
                  "DATA_VALIDESA;" & oPuntInterpretar.Dies(i).DataValidesa.ToString & vbCrLf & vbCrLf
    End If

    ' a + a + de les hores calculem TMax i TMin
    oPuntInterpretar.CalculaTempMin(oConfiguracio, oPuntInterpretar.Dies(i).FranjaMati, oPuntInterpretar.VariablesPG, oPuntInterpretar.DifHoraLocalUTC, oPuntInterpretar.Alçada, i - 1, iHoresRestar, sReport)
    sReport &= vbCrLf
    oPuntInterpretar.CalculaTempMax(oConfiguracio, oPuntInterpretar.Dies(i).FranjaMati, oPuntInterpretar.VariablesPG, oPuntInterpretar.DifHoraLocalUTC, oPuntInterpretar.Alçada, i - 1, iHoresRestar, sReport)
    sReport &= vbCrLf

    ' Ara mirem si tenim hores per aquest dia...
    For j As Integer = 1 To oPuntInterpretar.Dies(i).Hores.count

        With oPuntInterpretar

            ' VentVel (km/hora -> passar a Beaufort!)
            ' VentDir (ºC -> passar a CodiVent)
            ' Després caldrà juntar els dos valors a CodiVent per insertar en base de dades!

            .CalculaVentDir(oConfiguracio, .Dies(i).Hores(j), .VariablesPG, .DifHoraLocalUTC, .Alçada, i - 1, iHoresRestar, sReport, False)
            sReport &= vbCrLf

            .CalculaVentVel(oConfiguracio, .Dies(i).Hores(j), .VariablesPG, .DifHoraLocalUTC, .Alçada, i - 1, iHoresRestar, sReport, False)
            sReport &= vbCrLf

            If (.Dies(i).Hores(j).VentVel <> clsConfiguracio.NO_DADA_DOUBLE) And (.Dies(i).Hores(j).VentDir <> clsConfiguracio.NO_DADA_DOUBLE) Then
                .Dies(i).Hores(j).CodiVent = CalculaDirTaula(oConfiguracio, .Dies(i).Hores(j).VentDir) & GrauBeaufort(.Dies(i).Hores(j).VentVel, oConfiguracio.TaulaGrauBeaufort)
                sReport &= vbCrLf
            Else
                .Dies(i).Hores(j).CodiVent = ""
            End If

            .CalculaTempSuperficie(oConfiguracio, .Dies(i).Hores(j), .VariablesPG, .DifHoraLocalUTC, .Alçada, i - 1, iHoresRestar, sReport, False)
            sReport &= vbCrLf

            If (j = 1) Then
                .CalculaPluja(oConfiguracio, .Dies(i).Hores(j), .Dies(i).Hores(j).tipusHora, .VariablesPG, .DifHoraLocalUTC, .Alçada, i - 1, iHoresRestar, sReport, False)
                sReport &= vbCrLf
            Else
                .CalculaPluja(oConfiguracio, .Dies(i).Hores(j), .Dies(i).Hores(j - 1).tipusHora + 1, .VariablesPG, .DifHoraLocalUTC, .Alçada, i - 1, iHoresRestar, sReport, False)
                sReport &= vbCrLf
            End If

            .CalculaPressio(oConfiguracio, .Dies(i).Hores(j), .VariablesPG, .DifHoraLocalUTC, .Alçada, i - 1, iHoresRestar, sReport, False)
            sReport &= vbCrLf

            .CalculaNuvolositat(oConfiguracio, .Dies(i).Hores(j), .VariablesPG, .DifHoraLocalUTC, .Alçada, i - 1, iHoresRestar, sReport, False)
            sReport &= vbCrLf

            .CalculaSimbol(oConfiguracio, .Dies(i).Hores(j), .VariablesPG, .DifHoraLocalUTC, .Alçada, i - 1, moDB, iHoresRestar, sReport, False, True)
            sReport &= vbCrLf

        End With

我试着像这样使用它,但它似乎不起作用。我可以猜测它是关于&=运算符的东西或附加的错误。

更改后的代码:

Dim sReport As new StringBuilder

    Try

        iHoresRestar = dtDataElaboracio.Hour

        ' Per cada dia, calculem els valors de les tres franges i totes les hores...
        For i As Integer = 1 To oPuntInterpretar.Dies.Count

            ' DGARCIA: Per MeteoPlay3 no ens interessa que hi hagi diferència en l'hora local UTC, 
            '          ja que cada previsió s'ofereix des del mateir punt evaluat.
            oPuntInterpretar.DifHoraLocalUTC = 0

            If (oConfiguracio.Opcions_Meteo3D.LogPGs = True) Then
                ' Dades del report...
                sReport.Append("ID_PUNTGEOGRAFIC;" & oPuntInterpretar.IPuntGeografic & vbCrLf & _
                          "LATITUD_PUNTGEOGRAFIC;" & Math.Round(oPuntInterpretar.Latitud, 2) & vbCrLf & _
                          "LONGITUD_PUNTGEOGRAFIC;" & Math.Round(oPuntInterpretar.Longitud, 2) & vbCrLf & _
                          "ALCADA_PUNTGEOGRAFIC (metres);" & oPuntInterpretar.Alçada & vbCrLf & _
                          "TIPUS_PUNTGEOGRAFIC;" & IIf(oPuntInterpretar.Tipus = clsPuntGeografic.TipusPunt.Poblacio, "POBLACIO", "MUNTANYA") & vbCrLf & _
                          "DIF_HORALOCAL_UTC;" & oPuntInterpretar.DifHoraLocalUTC & vbCrLf & _
                          "DATA_MODEL;" & dtDataElaboracio.ToString & vbCrLf & _
                          "DATA_VALIDESA;" & oPuntInterpretar.Dies(i).DataValidesa.ToString & vbCrLf & vbCrLf)
            End If

            ' a + a + de les hores calculem TMax i TMin
            oPuntInterpretar.CalculaTempMin(oConfiguracio, oPuntInterpretar.Dies(i).FranjaMati, oPuntInterpretar.VariablesPG, oPuntInterpretar.DifHoraLocalUTC, oPuntInterpretar.Alçada, i - 1, iHoresRestar, sReport.ToString)
            sReport.AppendLine()
            oPuntInterpretar.CalculaTempMax(oConfiguracio, oPuntInterpretar.Dies(i).FranjaMati, oPuntInterpretar.VariablesPG, oPuntInterpretar.DifHoraLocalUTC, oPuntInterpretar.Alçada, i - 1, iHoresRestar, sReport.ToString)
            sReport.AppendLine()

更新------------------------

这是将sReport传递给它的函数之一:

Public Function CalculaVentDir(ByVal config As clsConfiguracio, _
                               ByRef unaHora As clsHora, _
                               ByVal colVars As clsVariables, _
                               ByVal DifHoraLocalUTC As Integer, _
                               ByVal Alçada As Double, _
                               ByVal difDies As Integer, _
                               ByVal horaModel As Integer, _
                               ByRef strReport As String, _
                      Optional ByVal UtilitzemDifHoraLocalUTC As Boolean = True _
                              ) As Boolean

    Dim U, V As Double
    Dim angle As Double
    Dim horaIni, posU, posV As Integer
    Dim ventDir As Double
    Dim strMsg As String
    Dim strTmp(7) As String

    Try

        If (colVars.CercaVariable(New clsVariable(33, 105, 10), posU) = True) And _
           (colVars.CercaVariable(New clsVariable(34, 105, 10), posV) = True) _
        Then

            If (UtilitzemDifHoraLocalUTC = True) Then
                horaIni = unaHora.tipusHora - DifHoraLocalUTC + difDies * 24 - horaModel
            Else
                horaIni = unaHora.tipusHora + difDies * 24 - horaModel
            End If

            strTmp(0) = "DIRECCIO DEL VENT"
            strTmp(1) = "Hora local"
            strTmp(2) = "Hora UTC"
            strTmp(3) = "Component U"
            strTmp(4) = "Component V"
            strTmp(5) = "Angle exacte"
            strTmp(6) = "Angle segons quadrant"
            strTmp(7) = "Angle aproximat"

            strMsg = "|Hora=" & unaHora.tipusHora & "|difDies=" & difDies & "|difHoraLocalUTC=" & DifHoraLocalUTC & "|horaModel=" & horaModel & "|horaIni=" & horaIni
            strTmp(1) &= ";" & unaHora.tipusHora
            strTmp(2) &= ";" & horaIni

            If (horaIni < 0) Then
                If (config.Opcions_Meteo3D.LogPGs = True) Then
                    RaiseEvent GetWarning("MESSAGE=No hem calculat la VentDir perquè la hora està fora dels marges" & strMsg & "|FUNCIO=CalculaVentDir_Hora", Me)
                End If
                unaHora.VentDir = clsConfiguracio.NO_DADA_DOUBLE
                CalculaVentDir = False
            End If

            U = colVars.Valors(posU - 1, horaIni)
            V = colVars.Valors(posV - 1, horaIni)

            strTmp(3) &= ";" & U
            strTmp(4) &= ";" & V

            If (U = clsConfiguracio.NO_DADA_DOUBLE) Or (V = clsConfiguracio.NO_DADA_DOUBLE) Then
                If (config.Opcions_Meteo3D.LogPGs = True) Then
                    RaiseEvent GetWarning("MESSAGE=No Assignem VentDir perquè no hem trobat dades de la hora " & horaIni & strMsg & "|FUNCIO=CalculaVentDir_Hora", Me)
                End If
                unaHora.VentDir = clsConfiguracio.NO_DADA_DOUBLE
                CalculaVentDir = False
            Else

                angle = Math.Atan2(Math.Abs(V), Math.Abs(U)) * 180 / Math.PI
                strTmp(5) &= ";" & angle

                If (U = 0) Then
                    If (V >= 0) Then ventDir = 180
                    If (V < 0) Then ventDir = 0
                Else
                    If (U > 0) And (V > 0) Then ventDir = 270 - angle
                    If (U < 0) And (V < 0) Then ventDir = 90 - angle
                    If (U > 0) And (V < 0) Then ventDir = 270 + angle
                    If (U < 0) And (V > 0) Then ventDir = 90 + angle
                End If

                strTmp(6) &= ";" & angle
                unaHora.VentDir = ventDir
                strTmp(7) &= ";" & angle
                CalculaVentDir = True

            End If

            For j As Integer = 0 To UBound(strTmp)
                strReport &= strTmp(j) & vbCrLf
            Next

        Else
            If (config.Opcions_Meteo3D.LogPGs = True) Then
                RaiseEvent GetWarning("MESSAGE=No Assignem VentDir perquè no hem trobat les variables 33 o 34|FUNCIO=CalculaVentDir_Hora", Me)
            End If
            CalculaVentDir = False
        End If

    Catch ex As Exception
        If (config.Opcions_Meteo3D.LogPGs = True) Then
            RaiseEvent GetError("MESSAGE=" & ex.Message & ", SOURCE=" & ex.StackTrace & ", FUNCIO=CalculaVentDir_Hora", Me)
        End If
        unaHora.VentDir = clsConfiguracio.NO_DADA_DOUBLE
        CalculaVentDir = False
    End Try

End Function

1 个答案:

答案 0 :(得分:0)

问题在于以下几点:

oPuntInterpretar.CalculaTempMin(oConfiguracio, oPuntInterpretar.Dies(i).FranjaMati, oPuntInterpretar.VariablesPG, oPuntInterpretar.DifHoraLocalUTC, oPuntInterpretar.Alçada, i - 1, iHoresRestar, sReport.ToString)

oPuntInterpretar.CalculaTempMax(oConfiguracio, oPuntInterpretar.Dies(i).FranjaMati, oPuntInterpretar.VariablesPG, oPuntInterpretar.DifHoraLocalUTC, oPuntInterpretar.Alçada, i - 1, iHoresRestar, sReport.ToString)

...和类似的,您将sReport.ToString()传递给方法。

您需要更改这些功能,甚至不要求报告。如果他们需要向报表添加内容,让他们返回一个字符串,然后在调用方法时追加结果:

sReport.Appdend(oPuntInterpretar.CalculaTempMin(oConfiguracio, oPuntInterpretar.Dies(i).FranjaMati, oPuntInterpretar.VariablesPG, oPuntInterpretar.DifHoraLocalUTC, oPuntInterpretar.Alçada, i - 1, iHoresRestar))

您也可以将方法更改为接受StringBuilder对象,但这种方式更好。该方法实际上并不需要知道报告字符串中已有的内容,而且函数的3个或4个以上参数都是代码气味。

如果此报告很大,即使使StringBuilder工作也可能无法解决您的OutOfMemory问题。如果您仍然遇到问题,接下来要查看的是使用 Stream ,例如FileStream,ASP.Net ReponseStreamConsole.Out流,您可以通过TextWriter抽象出所有这些。

最后,我们可以改进最初的StringBuilder翻译:

Dim reportBase As String = "ID_PUNTGEOGRAFIC;{0}{1}LATITUD_PUNTGEOGRAFIC;{2}{1}LONGITUD_PUNTGEOGRAFIC;{3}{1}ALCADA_PUNTGEOGRAFIC (metres);{4}{1}TIPUS_PUNTGEOGRAFIC;{5}{1}DIF_HORALOCAL_UTC;{6}{1}DATA_MODEL;{7}{1}DATA_VALIDESA;{8}{1}{1}"

Dim Report As New StringBuilder()
iHoresRestar = dtDataElaboracio.Hour
For Each die In oPuntInterpretar.Dies
    If oConfiguracio.Opcions_Meteo3D.LogPGs Then
        Report.AppendFormat(reportBase, _ 
            oPuntInterpretar.IPuntGeografic,vbCrLf, _ 
             Math.Round(oPuntInterpretar.Latitud, 2), _
             Math.Round(oPuntInterpretar.Longitud, 2), _
             oPuntInterpretar.Alçada, _
             IIf(oPuntInterpretar.Tipus = clsPuntGeografic.TipusPunt.Poblacio, "POBLACIO", "MUNTANYA"), _
             oPuntInterpretar.DifHoraLocalUTC, _
             dtDataElaboracio.ToString, _
             die.DataValidesa.ToString )
    End If

    '...

如果您能够更新到更新版本的Visual Studio(现在大多数情况下免费),我们可以进一步改进代码。我现在将使用变量名称上的匈牙利符号疣特别添加Microsoft 建议反对 。它现在只是report,而不是sReportpuntInterpretar而不是oPuntInterpretar