【问题标题】:Disposing static objects c#处理静态对象c#
【发布时间】:2013-12-10 13:33:13
【问题描述】:

我有一个实现 Excel 相关函数的静态类(类库)。

添加此 dll 作为对其他应用程序的引用,我正在尝试使用这些功能。

我知道当主程序终止时会释放静态对象。我可以以某种方式处理它吗?

在我的代码中,如果我调用CreateExcelDocument(excelFile),并且 Excel 实例正在后台运行(我可以在 Windows 的进程管理器中看到它)。但是,当我调用DisposeExcelDocument(); 时,实例仍然存在。我该如何处理它?

我的目标是逐个打开多个 Excel 文件,从当前打开的文件创建图表,然后关闭并继续下一个。有没有可能?

代码如下:

public static class ExcelUtils
{
    #region Private Members

    private static Application m_excelApp;
    private static Workbook m_excelWorkBook;
    private static Worksheet m_excelWorkSheet;

    #endregion Private Members

    #region Properties

    public static Worksheet ExcelWorkSheet
    {
        get { return m_excelWorkSheet; }
        set { m_excelWorkSheet = value; }
    }

    #endregion Properties

    #region Public Functions

    public static void CreateExcelDocument(string excelFile)
    {
        try
        {
            m_excelApp = new Application();
            m_excelApp.DisplayAlerts = false;
            m_excelWorkBook = m_excelApp.Workbooks.Add(Type.Missing);
            m_excelWorkSheet = (Worksheet)m_excelApp.ActiveSheet;
            m_excelApp.DefaultSheetDirection = (int)Constants.xlLTR;
            m_excelWorkSheet.DisplayRightToLeft = false;

            if (excelFile.CompareTo("") != 0)
            {
                m_excelWorkBook = m_excelApp.Workbooks.Open(excelFile);
                m_excelWorkSheet = (Worksheet)m_excelApp.Worksheets.get_Item(1);
                m_excelWorkSheet.Columns.ClearFormats();
                m_excelWorkSheet.Rows.ClearFormats();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            return;
        }
    }
    public static void DisposeExcelDocument()
    {
        try
        {
            m_excelApp.Quit();
            ReleaseObject(m_excelWorkSheet);
            ReleaseObject(m_excelWorkBook);
            ReleaseObject(m_excelApp);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            return;
        }
    }

    public static void ReleaseObject(object currentObject)
    {
        try
        {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(currentObject);
            currentObject = null;
        }
        catch (Exception ex)
        {
            currentObject = null;
            Console.WriteLine(ex.ToString());
            return;
        }
        finally
        {
            GC.Collect();
        }

    }

    public static uint GetNumberOfRowsOrCols(string excelFile, bool getRows)
    {
        CreateExcelDocument(excelFile);

        uint rowColNum = 0;

        if (getRows)
            rowColNum = (uint)m_excelWorkSheet.UsedRange.Rows.Count;
        else
            rowColNum = (uint)m_excelWorkSheet.UsedRange.Columns.Count;

        DisposeExcelDocument();

        return rowColNum;
    }

    #endregion Public Functions
}

【问题讨论】:

  • 您是否考虑过将这些作为静态变量开始?是的,如果你真的想要,你可以处理它们——但将它们作为实例变量会更干净,你可以让调用者根据需要创建单个实例或多个实例。毕竟,它固有地不是静态的。
  • 是的,但是我不能从外部调用公共函数,它们应该是静态的。
  • 嗯,是的,您还需要更改其余代码 - 但这将是重构它以改进它。
  • 看起来您希望对ReleaseObject 的调用也对null 对象进行调用,但是这不会使持有对它的引用的静态类变量为空。它当前所做的只是将对象的方法范围引用清空,而不是类范围引用。这可能就是您的实例“保留”的原因。您也无需致电GC.Collect。也就是说,我还建议进行重构以减少对静态全局对象的依赖,但这并不总是可能/可行的。
  • 您能否解释一下如何更改代码,以便我能够从外部项目调用位于类库中的非静态函数?

标签: c# excel object static dispose


【解决方案1】:

首先,我同意 cmets 将其设为非静态类。

但就您的问题而言,垃圾收集器不会收集对象,因为您没有将 null 设置为类成员,而只是 ReleaseObject 方法中的本地引用。

要使更改最少的类成员为空,将currentObject 参数作为ref 传递给ReleaseObject 方法,并且必须使用泛型而不是object 数据类型。所以方法会变成:

public static void ReleaseObject<T>(ref T currentObject) where T : class

要调用此方法,您将更改如下:

ReleaseObject(ref m_excelWorkSheet);

你可以保留ReleaseObject方法的主体,但我认为不需要调用GC.Collect(),如果你真的需要,那么最后只从DisposeExcelDocument调用一次,在你调用之后ReleaseObject 用于所有对象。

【讨论】:

  • 谢谢阿马尔。然后我得到错误:cannot convert from 'ref Microsoft.Office.Interop.Excel.Worksheet' to 'ref object'
  • 对不起,我完全错过了。多态性不能与ref 参数一起使用。我们必须在这里需要泛型。
  • 我已经更改了答案,希望现在可以使用。抱歉回复晚了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-26
  • 1970-01-01
  • 2013-03-08
相关资源
最近更新 更多