Можно ли создать обобщенный метод для освобождения COM-объектов?

Учитывая следующий код, метод ReleaseCOMObj () освободит исходный объект COM или неявно создаст копию и выпустит это?

private void TestRelease()
{
    Excel.Workbook workbook = excel.ActiveWorkbook;
    // do stuff
    ReleaseComObj(workbook);
}

private static void ReleaseComObj(Object obj)
{
    if (obj != null)
    {
        Marshal.ReleaseComObject(obj);
        obj = null;
    }
}

Обновление: Изменил метод на статический , См. Передача COM-объектов в качестве параметров в C # для объяснения того, почему параметр Object не может быть ref Object obj .

1
задан Community 23 May 2017 в 12:26
поделиться

2 ответа

Параметры C# передаются по ссылке.

Таким образом, исходный COM-объект будет освобожден, но исходная переменная не будет установлена ​​в null.

Чтобы установить для исходной переменной значение null, измените его на параметр ref, который передает переменную по ссылке. (и вызвать его с помощью ключевого слова ref)

Также, кстати, метод должен быть static, так как он не использует this.

1
ответ дан 2 September 2019 в 21:44
поделиться

Если вы хотите установить для ссылки нулевое значение, вы можете использовать общий метод, например:

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

Хотя устанавливать для ссылки нулевое значение не требуется. COM-объект будет освобожден в любом случае. См. документацию по RealeaseComObject(). Вы также можете рассмотреть возможность вызова FinalReleaseComObject().

Также вы можете создать объект-оболочку, который реализует IDisposable, и использовать блок using, чтобы обеспечить освобождение COM-объекта, даже если есть исключение.

class ComObjectCleanUp : IDisposable {

    private T obj;

    public ComObjectCleanUp(T obj) {
        this.obj = obj;
    }

    public void Dispose() {
        if (obj != null)
            Marshal.FinalReleaseComObject(obj);
    }
}

И ваш код выглядит следующим образом:

private void TestRelease()
{
    Excel.Workbook workbook = excel.ActiveWorkbook;
    using (var c = new ComObjectCleanUp(workbook))
    {
        // do stuff
    }
}

Хотя я признаю, что это не очень красиво, особенно учитывая количество COM-объектов, на которые вы будете ссылаться с помощью автоматизации Office, но в любом случае это идея.

1
ответ дан 2 September 2019 в 21:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: