Чтобы освободить вашу ссылку на целевой COM-объект, достаточно и предпочтительнее , чтобы просто вызвать Marshal.FinalReleaseComObject
, а , а не , чтобы вызвать сбор. Другими словами, вы выполнили свою обязанность выпустить свою ссылку, как только закончили с ней. Я не буду касаться вопроса FinalReleaseComObject
против ReleaseComObject
.
Это оставляет большой вопрос о том, почему люди выступают за звонки GC.Collect()
и WaitForPendingFinalizers()
?
Поскольку для некоторых конструкций сложно узнать, когда больше нет управляемых ссылок, поэтому вы не можете безопасно вызывать ReleaseComObject
. У вас есть два варианта: позвольте памяти нарастить и надеяться, что произойдет сбор или форсировать сбор. [см. примечание Стивена Янсена для голосования в комментариях]
Дополнительным примечанием является то, что установка target
в null
обычно не требуется и, в частности, не требуется в вашем примере кода. Установка нулевого значения для объектов является обычной практикой для VB6, поскольку он использует сборщик мусора на основе счетчика ссылок. Компилятор для C # достаточно умен (при сборке для выпуска), чтобы знать, что target
недоступен после его последнего использования и может быть GC'd, даже до выхода из области видимости. Под последним использованием я имею в виду последнее возможное использование, поэтому в некоторых случаях вы можете установить его на null
. Вы можете убедиться в этом сами с помощью кода ниже:
using System;
class GCTest
{
~GCTest() { Console.WriteLine("Finalized"); }
static void Main()
{
Console.WriteLine("hello");
GCTest x = new GCTest();
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("bye");
}
}
Если вы создаете релиз (например, CSC GCTest.cs), «Finalized» будет распечатываться между «hello» и «bye». Если вы создаете отладку (например, CSC / debug GCTest.cs), «Finalized» будет печататься после «пока», тогда как установка x
в ноль до Collect()
«исправит» это.