Нужно ли освобождать COM-объект на каждой итерации foreach? - PullRequest
14 голосов
/ 30 ноября 2010

Вот (потенциальная) проблема:

Я создаю COM-объект, а затем использую 'foreach' для перебора каждого элемента в коллекции, которую он возвращает.Нужно ли выпускать каждый отдельный элемент, который я повторяю в коллекции?(См. Код ниже.) Если это так, я не могу придумать, как эффективно освободить его из выражения 'finally', на случай, если при работе с элементом будет возникать ошибка.* Есть предложения?

private static void doStuff()
{
    ComObjectClass manager = null;

    try
    {
        manager = new ComObjectClass();
        foreach (ComObject item in manager.GetCollectionOfItems())
        {
            Log.Debug(item.Name);
            releaseComObject(item); // <-- Do I need this line?
                                    //     It isn't in a 'finally' block...
                                    //             ...Possible memory leak?
        }
    }
    catch (Exception) { }
    finally
    {
        releaseComObject(manager);
    }
}

private static void releaseComObject(object instance)
{
    if (instance != null)
    {
        try
        {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(instance);
        }
        catch
        {
            /* log potential memory leak */
            Log.Debug("Potential memory leak: Unable to release COM object.");
        }
        finally
        {
            instance = null;
        }
    }
}

1 Ответ

13 голосов
/ 30 ноября 2010

Вы не должны использовать оператор foreach с COM-объектом, так как ссылка делается за кулисами, к которым у вас нет никакого контроля над выпуском. Я бы переключился на цикл for и убедился бы, что вы никогда не используете две точки с COM-объектами.

Как это будет выглядеть:

try
{
    manager = new ComObjectClass();
    ComObject comObject = null;
    ComObject[] collectionOfComItems = manager.GetCollectionOfItems();
    try
    {
        for(int i = 0; i < collectionOfComItems.Count; i++)
        {
            comObject = collectionOfComItems[i];
            ReleaseComObject(comObject);
        }
    }            
    finally
    {
        ReleaseComObject(comObject);
    }
}
finally 
{
    ReleaseComObject(manager);
}
...