Безопасность потока WeakReference

При использовании WeakReference, как мы можем быть уверены, что цель не собирается между вызовами .IsAlive и .Target?

Например:

if (myWeakReference.IsAlive)
{
    // How can we be sure the object is still alive while here?
    ((MyType)myWeakReference.Target).Foo();
}

Ответы

Ответ 1

Просто запустите Target и проверьте, не является ли оно нулевым:

object target = myWeakReference.Target;
if (target != null)
{        
    ((MyType)target).Foo();
}

docs для IsAlive специально говорят:

Поскольку объект потенциально может быть регенерированный для сбора мусора сразу после свойства IsAlive возвращает true, используя это свойство не рекомендуется, если вы не тестируете только для ложного возвращаемого значения.

Ответ 2

Единственная цель свойства IsAlive - это ситуации, когда вы хотите предпринять какие-то действия, если цель WeakReference уже уничтожена, но где вы не хотите рисковать случайно, сохраняя ее дольше, чем необходимо. Если можно сказать, например,

  if (someWeakReference.Target == null)
    cleanup_related_object();

и сборщик мусора должен (по какой-либо причине) запускать сразу после кода, который оценил значение SomeWeakReference.Target, GC заметил бы, что существовала сильная ссылка на этот объект и исключала его сбор. С другой стороны, говоря:

  if (!someWeakReference.IsAlive)
    cleanup_related_object();

не было бы риска случайного продления срока жизни цели какой-либо цели WeakReference

Ответ 3

Вы не можете. Назначьте myWeakReference.Target к переменной и проверьте значение null.