Я тоже изучал этот вопрос, работая над приложением, ориентированным на COM / .Net-Interop, борясь с утечками, зависаниями и сбоями.
Краткий ответ: каждый раз, когда объект COM передается из среды COMв .NET.
Длинный ответ:
- Для каждого COM-объекта существует один объект RCW [Тест 1] [Ссылка 4]
- Счетчик ссылок увеличивается каждый разкогда объект запрашивается из COM-объекта (вызывая свойство или метод COM-объекта, который возвращает COM-объект, возвращаемый счетчик ссылок COM-объекта будет увеличиваться на единицу) [Тест 1]
- Счетчик ссылок не увеличивается наприведение к другим интерфейсам COM объекта или перемещение ссылки RCW вокруг [Тест 2]
- Счетчик ссылок увеличивается каждый раз, когда объект передается в качестве параметра в событии, вызванном COM [Ссылка 1]
Примечание: вы должны ВСЕГДА освобождать COM-объекты, как только вы закончите их использование.Передача этой работы в GC может привести к утечкам, неожиданному поведению и блокировке событий.Это в десять раз важнее, если вы обращаетесь к объекту не в потоке STA, в котором он был создан.[Ссылка 2] [Ссылка 3] [Мучительный личный опыт]
Надеюсь, я рассмотрел все случаи, но COM - непростое печенье.Приветствия.
Испытание 1 - счетчик ссылок
private void Test1( _Application outlookApp )
{
var explorer1 = outlookApp.ActiveExplorer();
var count1 = Marshal.ReleaseComObject(explorer1);
MessageBox.Show("Count 1:" + count1);
var explorer2 = outlookApp.ActiveExplorer();
var explorer3 = outlookApp.ActiveExplorer();
var explorer4 = outlookApp.ActiveExplorer();
var equals = explorer2 == explorer3 && ReferenceEquals(explorer2, explorer4);
var count2 = Marshal.ReleaseComObject(explorer4);
MessageBox.Show("Count 2:" + count2 + ", Equals: " + equals);
}
Output:
Count 1: 4
Count 2: 6, Equals: True
Испытание 2 - счетчик ссылок продолжение
private static void Test2(_Application outlookApp)
{
var explorer1 = outlookApp.ActiveExplorer();
var count1 = Marshal.ReleaseComObject(explorer1);
MessageBox.Show("Count 1:" + count1);
var explorer2 = outlookApp.ActiveExplorer();
var explorer3 = explorer2 as _Explorer;
var explorer4 = (ExplorerEvents_10_Event)explorer2;
var explorerObject = (object)explorer2;
var explorer5 = (Explorer)explorerObject;
var equals = explorer2 == explorer3 && ReferenceEquals(explorer2, explorer5);
var count2 = Marshal.ReleaseComObject(explorer4);
MessageBox.Show("Count 2:" + count2 + ", Equals: " + equals);
}
Output:
Count 1: 4
Count 2: 4, Equals: True
Источники, которые я включаю в дополнение к своему опыту и тестированию:
1.Johannes Passing's - Правила подсчета ссылок RCW! = Правила подсчета ссылок COM
2.Эран Сэндлер - Внутренняя часть Callable Wrapper и общие ошибки
3.Эран Сэндлер - Маршал. Выпуск КомаОбъект и спин процессора
4.MSDN - Runal Callable Wrapper