【问题标题】:Interop word processes not closing immediately互操作文字进程不会立即关闭
【发布时间】:2014-08-21 13:54:42
【问题描述】:

我正在使用多线程 WPF 应用程序中的互操作词库将 word 文档导出为 PDF,然后使用 MagickNet 库将它们转换为 PNG。

private void generateImagesFromOfficeDoc(Document currentDocument, CustomThread thread = null)
    {
        var token = tokenSource.Token;
        Microsoft.Office.Interop.Word.Application wordApplication = null;

        string[] filePath = currentDocument.OriginalPath.Split('\\');
        currentDocument.Filename = filePath[filePath.Length - 1].Trim();

        string fileNameWithoutExtension = System.IO.Path.GetFileNameWithoutExtension(currentDocument.Filename).Trim();
        string destinationPath;

        destinationPath = pngPath + "\\" + currentDocument.CreatedDate.Year.ToString() + "\\" + currentDocument.Specialty + "\\" + currentDocument.CreatedDate.Month + "\\" +
            currentDocument.CreatedDate.Day + "\\" + fileNameWithoutExtension;

        string pdfPath = magickNETTempDir + "\\" + fileNameWithoutExtension + ".pdf";
        string pdfName = fileNameWithoutExtension + ".pdf";
        string tempFile = magickNETTempDir + "\\" + currentDocument.Filename;

        try
        {
            // Copying the file from the original location to the temp folder. ** This is because impersonation have issues with the interop library.
            File.Copy(currentDocument.OriginalPath, tempFile);

            // Create the directory if it does not exist.
            if (!Directory.Exists(destinationPath))
            {
                Directory.CreateDirectory(destinationPath);
            }

            /************ CONVERTING THE DOCUMENT TO PDF ***************/
            wordApplication = new Microsoft.Office.Interop.Word.Application();
            // Opening the word document
            var wordDocument = wordApplication.Documents.Open(tempFile);
            var pageCount = wordDocument.ComputeStatistics(Microsoft.Office.Interop.Word.WdStatistic.wdStatisticPages, false);
            // Exporting the document to the PDF
            wordDocument.ExportAsFixedFormat(pdfPath, Microsoft.Office.Interop.Word.WdExportFormat.wdExportFormatPDF);
            // Closing the document and the application.
            ((Microsoft.Office.Interop.Word._Document)wordDocument).Close(false);
            ((Microsoft.Office.Interop.Word._Application)wordApplication).Quit(false);
   }

每个线程都会打开一个 word 应用程序,并且应该在导出文档后关闭它。以同样的方法,我将导出的 PDF 转换为 PNG,然后删除临时 PDF(代码被排除,因为我认为它与问题无关)。

这个过程完成了它的工作,但是由于我正在转换数千个文档,所以我在后台得到了相当多的文字处理,占用了我的 RAM。这些进程最终会自行关闭,但速度非常慢,因此我最终会在后台处理越来越多的进程。这不会发生在所有机器上,也不会发生在每个文档上,所以我不确定出了什么问题。

有没有办法强制关闭它们?我已经尝试过按名称杀死进程的方法,但这需要应用程序窗口可见,这是我不想要的。

【问题讨论】:

  • 您是否尝试过在单独的应用程序域中运行此代码并在完成后卸载该域?
  • 您是否尝试过创建一次Word.Application 并将其用于所有Document.Open 呼叫?我过去曾将 Word 用于其拼写检查库,我发现它会在调用 Close/Quit 后保持打开一段时间。
  • 为什么不能使用一个Interop 实例?如果您尝试对此进行多线程处理,问题是可能只有 1 个 IO 线程。

标签: c# wpf multithreading ms-word office-interop


【解决方案1】:

我在使用Microsoft.Office.Interop.Excel dll 时遇到了类似的问题。我发现在Excel 会从Windows 任务管理器进程选项卡中消失之前,我必须释放我一直在使用的所有COM 对象。需要明确的是,我会关闭应用程序,但在我释放 COM 对象之前,它的进程将在任务管理器中保持可见。试试这样的:

private void ReleaseComObjects(bool isQuitting)
{
    try
    {
        if (isQuitting)
        {
            workbook.Close(false, missing, missing); 
            excelApplication.Quit();
        }
        Marshal.ReleaseComObject(workbooks);
        Marshal.ReleaseComObject(workbook);
        if (worksheets != null) Marshal.ReleaseComObject(worksheets);
        Marshal.ReleaseComObject(worksheet);
        Marshal.ReleaseComObject(excelApplication);
        workbook = null;
        worksheets = null;
        worksheet = null;
        excelApplication = null;
    }
    catch { }
    finally { GC.Collect(); }
}

private void ReleaseComObjects()
{
    ReleaseComObjects(false);
}

【讨论】:

  • 按预期工作。它会稍微减慢应用程序的速度,但在这种情况下,我很高兴为可靠性牺牲一点速度。非常感谢。
  • 我看不出释放 COM 对象会如何减慢速度,但我很高兴你解决了问题。
  • 自修复以来,我的任务似乎正在同步运行。我使用 4 个任务,所有 4 个任务都使用不同的文字处理,但一次只有一个将 doc 转换为 pdf,然后第二个任务将做同样的事情,然后是第三个和第四个。我回滚到之前的版本,它们都异步同时工作。所以在某种程度上,我失去了多线程,不知道为什么。
  • 哇,这是一个不幸的权衡。我不能告诉你为什么会这样,但如果你问另一个问题,也许链接到这个问题,其他人也许可以提供帮助。
  • 谢谢。那时我可能不得不问另一个问题,但我也意识到 Marshal.ReleaseComObject(wordDocument) 释放 word 文档对象需要 15-20 秒,这似乎不对。
【解决方案2】:

Marshal.ReleaseComObject(wordDocument) 在 Web 应用程序中大约需要 15-20 秒

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-10
    • 2017-08-12
    • 2020-11-08
    • 1970-01-01
    相关资源
    最近更新 更多