【问题标题】:Excel objects not getting disposed sometimesExcel 对象有时不会被处理
【发布时间】:2012-02-08 00:03:40
【问题描述】:

我有这段代码用于从 excel 单元格中读取:

 public T GetValue<T>(string testsheet, string range)
    {
        Application excelApplication    = null;
        Workbooks workBooks             = null;
        Workbook activeWorkBook         = null;
        Worksheet activeWorkSheet       = null;

        try
        {
            excelApplication    = new Application();
            workBooks           = excelApplication.Workbooks;
            activeWorkBook      = workBooks.Open(workBook);

            activeWorkSheet     = activeWorkBook.ActiveSheet;
            var cells           = activeWorkSheet.get_Range(range);
            return cells.Value2;

        }
        catch (Exception theError)
        {
            Console.WriteLine(theError.Message);
            throw theError;
        }
        finally
        {         
            ReleaseComObject(activeWorkSheet);
            ReleaseComObject(activeWorkBook);
            ReleaseComObject(workBooks);
            ReleaseComObject(excelApplication);
        }            
    }

我还有一个 Set value 方法,它将值设置为单元格,如下所示:

public void SetValue<T>(string testsheet, string range, T value)
    {
        Application excelApplication = null;
        Workbooks workBooks = null;
        Workbook activeWorkBook = null;
        Worksheet activeWorkSheet = null;

        try
        {
            excelApplication = new Application();
            workBooks = excelApplication.Workbooks;
            activeWorkBook = workBooks.Open(workBook);

            activeWorkSheet = activeWorkBook.ActiveSheet;
            var cells = activeWorkSheet.get_Range(range);
            cells.Value2 = value;
            activeWorkBook.Save();             
        }
        catch (Exception theError)
        {
            Console.WriteLine(theError.Message);
            throw theError;
        }
        finally
        {
            if (activeWorkBook != null)
                activeWorkBook.Close();

            ReleaseComObject(excelApplication);
            ReleaseComObject(workBooks);
            ReleaseComObject(activeWorkBook);
            ReleaseComObject(activeWorkSheet);                                                
        }           
    }

这是我的 ReleaseComObject:

  private static void ReleaseComObject<T>(T comObject) where T : class
    {
        if (comObject != null)
            Marshal.ReleaseComObject(comObject);
    }

我已经编写了一个测试,以确保 excel 对象按如下方式正确处理:

  [Test]
    public void Should_dispose_excel_objects_created_after_io_operation()
    {
        var expected = Process.GetProcesses().Count(process => process.ProcessName.ToLower() == "excel");

        var automationClient = new ExcelAutomation.ExcelAutomationClient(ExcelSheet);

        automationClient.SetValue("Sheet1", "A1", 1200);
        automationClient.GetValue<double>("Sheet1", "A1");

        var actual = Process.GetProcesses().Count(process => process.ProcessName.ToLower() == "excel");

        actual.Should().Be(expected, "Excel workbook is not disposed properly. There are still excel processess in memory");
    }

如果我只调用 SetValue 方法,则此测试通过,但是在调用 GetValue 时它会失败。但是我在任务管理器中看不到 Excel.exe。知道为什么会这样吗?我的 GetValue 函数有问题吗?

【问题讨论】:

  • 我相信get_Range 返回一个COM 对象,所以你也应该释放它。虽然,您在两种方法中都调用它。
  • 它与处置无关。您正在编写 C 代码,手动管理内存。随着不可避免的错误产生,“泄漏”内存。您没有为 cells 对象引用调用 ReleaseComObject()。只是不要写这样的代码,没有意义。垃圾收集器已经知道如何做到这一点。如果您出于某种原因想加快速度,请调用 GC.Collect()。只要你有充分的理由。
  • 如果你比较这两种方法,我在做几乎相同的事情。如果我不调用 ReleaseComObject,则 excel 实例会在内存中徘徊。只有在调用它之后它才会消失。即使在这种情况下它也会消失,但测试没有通过。
  • 使用杀死应用程序win32 API stackoverflow.com/questions/7956519/…
  • @HansPassant : 这就是您针对 Excel 编写代码的方式 :) support.microsoft.com/kb/317109

标签: c# excel tdd


【解决方案1】:

当你处理完对象后,使用

GC.Collect();

这就是我处理 Excel 对象的方式

        private void releaseObject(object obj)
    {
        try
        {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
            obj = null;
        }
        catch (Exception ex)
        {
            obj = null;
            MessageBox.Show("Exception Occured while releasing object " + ex.ToString());
        }
        finally
        {
            GC.Collect();
        }
    }

【讨论】:

    猜你喜欢
    • 2021-12-15
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 2019-04-29
    • 2017-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多