C# 如何在.NET中处理COM对象的事件时释放所有COM对象

C# 如何在.NET中处理COM对象的事件时释放所有COM对象,c#,excel,memory-management,com,C#,Excel,Memory Management,Com,我正在C#中使用COM Excel应用程序类。我在关闭前处理了工作簿。但现在我无法正确释放COM对象 请注意,在处理此事件之前,我成功地释放了COM对象,并且在注释这部分代码时,我的应用程序工作正常 什么COM对象没有从内存中释放,如何正确释放它 编辑: 我所做的: public void Init() { ... application = new Excel.Application(); application.WorkbookBeforeClose += new Exce

我正在C#中使用COM Excel应用程序类。我在关闭前处理了
工作簿
。但现在我无法正确释放COM对象

请注意,在处理此事件之前,我成功地释放了COM对象,并且在注释这部分代码时,我的应用程序工作正常

什么COM对象没有从内存中释放,如何正确释放它

编辑: 我所做的:

public void Init()
{
   ...
   application = new Excel.Application();
   application.WorkbookBeforeClose += new Excel.AppEvents_WorkbookBeforeCloseEventHandler(application_WorkbookBeforeClose);
}
...
void application_WorkbookBeforeClose(Excel.Workbook Wb, ref bool Cancel)
    {
        if (WorkbookBeforeClose != null)
        {
            ExcelCloseEventArgs args = new ExcelCloseEventArgs();
            WorkbookBeforeClose(this, args);
            Cancel = args.Cancel;
        }
        else
            Cancel = false;
    }
...
private void closeExcel()
    {
        try
        {
            if (workbook != null)
            {
                workbook.Close(false);
            }
        }
        catch (Exception e) { }
        finally
        {
            if (workbooks != null)
                Marshal.ReleaseComObject(workbooks);
            if (workbook != null)
                Marshal.ReleaseComObject(workbook);
        }

        try
        {
            if (application != null)
            {
                application.WorkbookBeforeClose -= handler;
                application.Quit();
                Marshal.ReleaseComObject(application);
                Marshal.ReleaseComObject(handler);
                process.WaitForExit();
            }
        }
        catch (Exception e) { throw; }
        finally
        {

        }

        workbook = null;
        workbooks = null;
        application = null;
        if (process != null && !process.HasExited)
            process.Kill();
        if (threadCulture != null)
            Thread.CurrentThread.CurrentCulture = threadCulture;
        initialized = false;
    }

应用程序在第
行进程中暂停。WaitForExit()

内存管理在.NET中是自动的。自己显式调用Marshal.ReleaseComObject()是一个错误。这不仅仅是因为过早地使RCW崩溃很容易,尤其是因为引用计数通常是隐藏的。索引器和事件是棘手的。缺少一个ReleaseComObject调用就足以让它退回到垃圾收集器来处理它。GC需要一些时间来释放内存(和引用计数)是一个特性,而不是一个bug


如果您真的希望COM服务器按需退出,而不是让垃圾收集器处理它,那么请将所有引用设置为null,取消订阅事件处理程序并调用GC.Collect()。不需要ReleaseComObject调用。查看专业人士的见解。

我通过在
closeExcel
方法中修改这些代码行来修复代码:

if (application != null)
{
   application.WorkbookBeforeClose -= new Excel.AppEvents_WorkbookBeforeCloseEventHandler(application_WorkbookBeforeClose);
   application.Quit();
   Marshal.ReleaseComObject(application);
   GC.Collect();
   GC.WaitForPendingFinalizers();
   process.WaitForExit(100);
}

我认为问题在于垃圾收集。我的物品没有完全收集。

你能告诉我们你做了什么吗?这样我们就能知道怎么了?谢谢!你的建议对我很管用。所以我把正确答案改成了你的。