Как освободить все COM-объекты при обработке его события в .NET - PullRequest
2 голосов
/ 06 июля 2011

Я использую класс приложения COM Excel в C #.Я занимался WorkbookBeforeClose.Но теперь я не могу правильно освободить 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;
    }

Приостановка работы приложения В строке process.WaitForExit().

Ответы [ 2 ]

3 голосов
/ 06 июля 2011

Управление памятью происходит автоматически в .NET. Явный вызов Marshal.ReleaseComObject () самостоятельно является ошибкой. Не только потому, что вы можете легко разбить RCW, когда вы делаете это слишком рано, но особенно потому, что счетчики ссылок часто скрыты. Индексаторы и события являются хитрыми. Достаточно одного пропущенного вызова ReleaseComObject, чтобы он вернулся к сборщику мусора, который позаботился об этом. То, что сборщик мусора занимает некоторое время для освобождения памяти (и количества ссылок) - это особенность, а не ошибка.

Если вы действительно хотите, чтобы COM-сервер завершал работу по требованию, а не позволял сборщику мусора позаботиться об этом, тогда установите все ссылки, которые у вас есть, чтобы обнулить, отмените подписку на обработчики событий и вызовите GC.Collect (). Вызовы ReleaseComObject не требуются. Проверьте это сообщение в блоге для понимания от профи.

0 голосов
/ 09 июля 2011

Я исправил свой код, изменив эти строки кода в методе closeExcel:

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

Я думаю, что проблема была в сборке мусора. Мой объект не собирался полностью.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...