异步 PDF 创建的 IOException 问题

IOException issue with asynchronous PDF creation

我有一个异步方法,可以根据从数据库检索到的 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.0M2D4TCB.REJLH3JZY2.TQC\<clickonce app>1964.fo' because it is being used by another process.

除了发生此异常时偶尔出现的孤立 .fo 文件外,一切都按预期工作。有人对我如何找出问题所在有任何建议吗?

The only part of either method ... that even does anything with the .fo file is in FormatObjectToPdf 看来 AsyncXmlToPdf 也会尝试在其上打开一个 streamwriter。

如果其他一些 BackGroundWorker、Thread 或 Task 有可能也在处理同一组文件,那么 AsyncXmlToPdf 和 [= 中可能会使用同一个文件13=]。 MSDN 在 File.Exists 条目中对此发出警告:

Be aware that another process can potentially do something with the file in between the time you call the Exists method and perform another operation on the file, such as Delete.

在您的情况下,看起来可能是抛硬币,异常将在哪个方法中发生。

如果意外双击可以启动同一个进程两次,则可能是同一个文件同时在两种方法中使用。您可以添加另一个测试,看看您是否可以打开文件进行 ReadWrite。鉴于该文件不应该存在,您至少可以确定原因。

阻止启动一组以上作业的某种标志可能是最终解决方案。