异步PDF创建的IOException问题

时间:2015-04-10 00:17:49

标签: vb.net pdf asynchronous io

我有一个异步方法,可以从数据库中检索的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中,并且该方法具有CatchIOException。为什么在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文件之外,其他所有内容都按预期工作。任何人都有任何关于如何找出问题所在的建议?

1 个答案:

答案 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文件。鉴于该文件尚未存在,您至少可以确定原因。

防止启动多个作业集的某种标志可能是最终的解决方案。