【问题标题】:Lingering Excel Process挥之不去的Excel流程
【发布时间】:2018-11-10 16:53:24
【问题描述】:

我正在做一个 Windows 服务,我正在使用 Microsoft.Office.Interop.Excel 创建一个新的 excel 文件,对其进行编辑并保存。

做完之后,关闭相应的对象(工作表、工作簿),退出excel应用,Marshal释放COM对象,这个过程还在拖。

    private void doWork()
    {
        var excelApp = new MsExcel.Application();
        var workBooks = excelApp.Workbooks;
        var workbook = excelApp.Workbooks.Add();
        var sheets = workbook.Sheets;
        _worksheet = workbook.Sheets[1];

        //Do Work Here

        _worksheet.SaveAs(filePath);
        workbook.Close(false,System.Reflection.Missing.Value,System.Reflection.Missing.Value);
        workBooks.Close();
        releaseObject(_worksheet);
        releaseObject(sheets);
        releaseObject(workbook);
        releaseObject(workBooks);
        excelApp.Quit();
        releaseObject(excelApp);

    }

    private void releaseObject(object obj)
    {
        try
        {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
            obj = null;
        }
        catch (Exception ex)
        {
            _log.Error($"Unable to release object {obj} Error:" + ex.ToString());
            obj = null;
        }
        finally
        {
            GC.Collect();
        }
    }

我看到了一些其他建议释放对象的帖子,以及对工作簿和工作表的引用。不确定,为什么这仍然不起作用。

【问题讨论】:

  • _worksheet 是一个字段吗?这可能是造成它的原因。您可以尝试将其作为局部变量并将其传递给需要它的方法。
  • 所以你标记了这个 excel,但这不是 excel 问题...
  • 这不是一个 excel 问题@SolarMike? 我正在使用 Microsoft.Office.Interop.Library 创建一个新的 excel 文件,对其进行编辑并保存。
  • 什么叫图书馆?用excel打开文件并运行宏?还是来自不同的程序?
  • @stuartd:好点。我会尝试不使用该字段。

标签: c# excel com office-interop


【解决方案1】:

Microsoft 目前不推荐也不支持任何无人值守、非交互式客户端应用程序或组件(包括 ASP、ASP.NET、DCOM 和 NT 服务)的 Microsoft Office 应用程序自动化,因为 Office 可能表现出不稳定Office 在此环境中运行时出现的行为和/或死锁。

如果您要构建在服务器端上下文中运行的解决方案,您应该尝试使用已确保无人值守执行安全的组件。或者,您应该尝试找到允许至少部分代码在客户端运行的替代方案。如果您使用服务器端解决方案中的 Office 应用程序,该应用程序将缺少许多成功运行所需的功能。此外,您将承担整体解决方案稳定性的风险。在Considerations for server-side Automation of Office 文章中阅读更多相关信息。

作为一种解决方法,您可以考虑使用One XML SDK 或任何其他为服务器端或服务执行而设计的第三方组件。

【讨论】:

    【解决方案2】:

    您不应该调用 ReleaseComObject。那是一个很久以前开始的老太太的故事,但是it is incorrect

    如果您看到 excel 实例仍然存在,这可能意味着您的程序在没有运行垃圾收集器和仍然保留在 com 对象的引用的情况下终止。解决问题的最佳方法是完全摆脱您的发布功能,然后在doWork() 方法返回后调用GC.Collect()

    private void doWork()
    {
        try
        {
            doWorkImpl();
        }
        finally
        {
            GC.Collect(); //The GC collect needs to be here, after the scope of doWorkImpl ends.
            GC.WaitForPendingFinalizers(); //The excel instance gets closedin the finalizer.
        }
    }
    
    private void doWorkImpl()
    {
        var excelApp = new MsExcel.Application();
        var workBooks = excelApp.Workbooks;
        var workbook = excelApp.Workbooks.Add();
        var worksheet = workbook.Sheets[1]; //This needs to be a local variable, not a class variable.
    
        //Do Work Here
    
        worksheet.SaveAs(filePath);
        workbook.Close(false,System.Reflection.Missing.Value,System.Reflection.Missing.Value);
        workBooks.Close();
        excelApp.Quit();
    
    }
    

    只要没有引发异常并且成功调用excelApp.Quit(),这应该会导致 excel 实例运行。

    但是,如果您只使用 xlsx 文件而不是 xsl 文件,我会高度建议您远离 com 互操作,而只使用 the SDK microsoft provides 进行直接交互带有 .xlsx 文件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-27
      • 2010-09-05
      • 2012-10-20
      • 1970-01-01
      • 1970-01-01
      • 2012-11-15
      • 2013-10-17
      相关资源
      最近更新 更多