Тестирование / проверка слабой ссылки - PullRequest
16 голосов
/ 06 мая 2011

Я хотел бы убедиться, что код, устанавливающий WeakReference, не случайно содержит сильную ссылку на объект, на который ссылаются. (Вот пример того, как легко это сделать случайно.)

Похоже ли это на лучший способ проверить непреднамеренные сильные ссылки?

TestObject testObj = new TestObject();
WeakReference wr = new WeakReference(testObj);

// Verify that the WeakReference actually points to the intended object instance.
Assert.Equals(wr.Target, testObject);

// Force disposal of testObj;
testObj = null;
GC.Collect();
// If no strong references are left to the wr.Target, wr.IsAlive will return false.
Assert.False(wr.IsAlive);

Ответы [ 2 ]

12 голосов
/ 07 июня 2011

Я связался с Microsoft по этому поводу и узнал / подтвердил, что:

  • GC.Collect() принудительно блокирует сборку мусора.
  • Когда GC.Collect() запускается, он выигрывает 't таинственно пропустить подходящие для коллекции объекты.Предсказуемые правила следуют для определения, какие объекты собирать.Пока вы работаете с пониманием этих правил (то есть, как обрабатываются финализуемые объекты), вы можете принудительно уничтожить определенный объект, хотя память, используемая уничтоженным объектом, может или не может быть освобождена.

Больше информации в моем блоге: Можно ли принудительно собирать мусор в .Net?

4 голосов
/ 06 мая 2011

Я сделал это только вчера.Вот что я должен был добавить, чтобы убедиться, что сбор произошел до вашего последнего утверждения:

        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.WaitForFullGCComplete();
        GC.Collect();

Если после этого .IsAlive все еще имеет значение true, вероятно, где-то еще есть надежная ссылка.* Между прочим - обязательно НЕ проверяйте .IsAlive, когда вы получаете доступ к своей цели WeakReference.Чтобы избежать состояния гонки между проверкой .IsAlive и .Target, сделайте следующее:

var r = weakRef.Target AS Something;
if (r != null)
{
    ... do your thing
}
...