我刚刚开始使用多线程。我正在运行我的多线程代码的测试,但我得到一个OutOfMemory异常。获取OutOfMemory异常线程
代码使用新线程将PS转换为PDF。这项任务大约需要半秒钟的时间,所以对于这个测试,我只是简单地休息一秒钟,以确保我没有太多的任务运行。它在抛出OutOfMemory异常之前做了900多次。
我知道我需要使用线程池,信号量或任务并行来限制我的线程,但现在我只是在测试我的线程。
Dim sr As New StreamReader(PSTempFolder & "PDFWrite.txt")
Do While Not sr.EndOfStream
'get PS
Dim FileNamePS As String = sr.ReadLine
'get folder
Dim CustFolder As IO.DirectoryInfo
CustFolder = GetCustFolder(FileNamePS)
'set PDF path and name
FileNamePDF = CustFolder.FullName & "\Statement.pdf"
Dim t As Thread
Dim n As ConvertPDF = Nothing
n = New ConvertPDF
n.DeletePS = False
n.PSFileName = FileNamePS
n.PDFFileName = FileNamePDF
t = New Thread(AddressOf n.callConvertToPDF)
t.Start()
'wait
Thread.Sleep (1000)
Loop
sr.Close()
看来它必须创建太多的线程,而不是清理旧的线程。在创建新线程之前如何清理/处理线程?我想第二个解决方案(在这种情况下)将简单地使用相同的线程(我想我可以做到这一点),但对于这个问题,我更感兴趣的是处理线程和释放内存。我怎么做?
这里是代码的其余部分:
Class ConvertPDF
Public PSFileName As String
Public PDFFileName As String
Public DeletePS As Boolean = False
Delegate Function ConvertToPDFdel(ByVal svPsFileName As String, _
ByVal svPDFName As String, _
ByVal DeletePS As Boolean) As Integer
Sub callConvertToPDF()
Dim dlgt As New ConvertToPDFdel(AddressOf ConvertToPDF)
Dim i As Integer = dlgt.Invoke(PSFileName, PDFFileName, DeletePS)
End Sub
End Class
Public Function ConvertToPDF(ByVal svPsFileName As String, _
ByVal svPDFName As String, _
ByVal DeletePS As Boolean) As Integer
'check for file
If Not IO.File.Exists(svPsFileName) Then
Throw New ApplicationException(svPsFileName & " cannot be found")
End If
'delete old file
If IO.File.Exists(svPDFName) Then IO.File.Delete(svPDFName)
'convert
Dim myProcInfo As New ProcessStartInfo
myProcInfo.FileName = DanBSolutionsLocation & "Misc\GhostScript\GSWIN32C.EXE"
myProcInfo.Arguments = "-sDEVICE=pdfwrite -q -dSAFER -dNOPAUSE -sOUTPUTFILE=""" & svPDFName & """ -dBATCH """ & svPsFileName & """"
'Debug.Print(myProcInfo.Arguments)
'do the conversion
Dim myProc As Process = Process.Start(myProcInfo)
'wait for finish (no more than 20 seconds)
myProc.WaitForExit(20000)
myProcInfo = Nothing
myProc.Dispose()
'delete PS
If DeletePS Then
If IO.File.Exists(svPDFName) Then IO.File.Delete(svPsFileName)
End If
End Function
编辑:我做了GroverBoy的代码和我的,结果是不确定之间有一些更多的测试。有时候一个人有时候会好一些。也许这两个真的是一样的,问题在别处。
新线程启动一个需要0.55秒才能完成的新进程。如果主线程每次迭代等待1秒,这应该意味着我们永远不会有多个线程或一次打开的文件。为什么不是这样?
实际发生的事情会有所不同,我不知道为什么。我正在主线程上测试100和1秒等待的循环。我通常会看到任务管理器的性能选项卡。有时我会运行代码,线程数量会在2-6个额外之间波动,并且Commit Charge将在1044M到1150M之间波动。这就是我要的。其他时间我运行相同的代码(100次迭代),并且线程数量不断上升到63以上。 Commit Charge持续从10.44M增长到超过1272M。
我该怎么做才能确保程序能够一致地清理线程?
如果'callConvertToPDF'运行完成,新线程将退出并清理。你在'callConvertToPDF'里释放流吗?我想PS或PDF文件在转换完成后保持打开状态。 – kennyzx 2014-10-28 04:29:55
@kennyzx感谢您的评论,这是有帮助的。我发布了其他代码以防万一,但GroverBoy的答案造成了不同。谢谢。 – 2014-10-29 01:57:15
如果我正确理解此代码,您正在读取超过900个文件名,并且您为每个文件启动一个新线程和一个新进程。那是对的吗? – Enigmativity 2014-10-29 02:21:05