我有一个异步方法,可以从数据库中检索的XML创建PDF文件。一切都很好,但偶尔我得到一个IOException
,因为当我在创建PDF后尝试清理临时.fo
文件时,该文件仍在使用中。
Public Sub FormatObjectToPdf(ByVal intRxNo As Integer, ByVal strSourceFileName As String)
Dim startInfo As New ProcessStartInfo
Dim strPdfFile As String = g_strRootPath & "Paperwork\" & intRxNo & "M.pdf"
' if the PDF file already exists, no need to re-create it
If Not File.Exists(strPdfFile) Then
Try
startInfo.Arguments = "-fo """ & strSourceFileName & """ -pdf """ & strPdfFile & """"
startInfo.FileName = g_strAppPath & "FO.NET\fonet.exe"
startInfo.UseShellExecute = True
startInfo.WindowStyle = ProcessWindowStyle.Hidden
Using proc As Process = Process.Start(startInfo)
proc.WaitForExit()
If proc.HasExited Then
proc.Dispose()
End If
End Using
Catch ex As Exception
Call InsertLog("ErrorLog", "FormatObjectToPdf: " & ex.Message, ex)
MessageBox.Show(ex.Message, "Create PDF", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
End Try
End If
' wait 3 seconds to allow file to be released
System.Threading.Thread.Sleep(3000)
' delete the source FO file when processing is complete
If File.Exists(strSourceFileName) Then
Try
File.Delete(strSourceFileName)
Catch iEx As IOException
Call InsertLog("ErrorLog", "Could not delete file '" & strSourceFileName & "': " & iEx.Message, iEx)
Catch ex As Exception
Call InsertLog("ErrorLog", "Error deleting file '" & strSourceFileName & "': " & ex.Message, ex)
End Try
End If
End Sub
从另一个方法FormatObjectToPdf
调用AsyncXmlToPdf
方法,该方法实际上是抛出IOException
的方法。我最初认为该异常位于FormatObjectToPdf
,因为我正在删除.fo
文件,所以我添加了Sleep(3000)
以查看是否给它几秒钟会有所帮助。
以下是AsyncXmlToPdf
:
Public Sub AsyncXmlToPdf(ByVal state As Object)
Dim intRxNo = state(0)
Dim flgPrintResult As Boolean = state(1)
Dim strFileName As String = g_strAppPath & intRxNo & ".fo"
Dim strOutput As String
Dim strPdfFile As String = g_strRootPath & "Paperwork\" & intRxNo & "M.pdf"
Try
If File.Exists(strPdfFile) Then
File.Delete(strPdfFile)
End If
If Not File.Exists(strPdfFile) AndAlso Not File.Exists(strFileName) Then
strOutput = XmlToFormatObject(intRxNo, g_strAppPath & "FO.NET\immfo.xsl")
Using writer As StreamWriter = New StreamWriter(strFileName)
writer.Write(strOutput)
End Using
Call FormatObjectToPdf(intRxNo, strFileName)
End If
Catch ex As Exception
Call InsertLog("ErrorLog", "AsyncXmlToPdf: " & ex.Message, ex)
End Try
End Sub
除strFileName
声明之外的任何一种方法的唯一部分,即使对.fo
文件执行任何操作,都在FormatObjectToPdf
中,并且该方法具有Catch
块IOException
。为什么在AsyncXmlToPdf
中捕获异常?这是实际的错误消息:
3/25/2015 11:15 AM: [IOException] AsyncXmlToPdf: The process cannot access the file 'C:\Users\<username>\AppData\Local\Apps\2.0\1M2D4TCB.REJ\3LH3JZY2.TQC\<clickonce app>\561964.fo' because it is being used by another process.
当发生此异常时,除了偶尔出现的孤立.fo
文件之外,其他所有内容都按预期工作。任何人都有任何关于如何找出问题所在的建议?
答案 0 :(得分:2)
The only part of either method ... that even does anything with the .fo file is in FormatObjectToPdf
似乎AsyncXmlToPdf
也会尝试在其上打开一个输家。
如果某些其他BackGroundWorker,Thread或Task也可能在同一组文件上工作,则AsyncXmlToPdf
和{{1}可能会使用同一个文件}。 MSDN在FormatObjectToPdf
条目中警告这一点:
请注意,在您调用Exists方法和对文件执行其他操作(例如Delete)之间,另一个进程可能会对文件执行某些操作。
在你的情况下,看起来它可能是一个硬币翻转哪种方法会发生异常。
如果意外双击可以两次启动相同的进程,则可能同时在两种方法中使用相同的文件。您可以添加另一个测试,以查看是否可以打开ReadWrite文件。鉴于该文件尚未存在,您至少可以确定原因。
防止启动多个作业集的某种标志可能是最终的解决方案。