以下代码给出了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
答案 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 ReponseStream
或Console.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
,而不是sReport
和puntInterpretar
而不是oPuntInterpretar
。