Пользовательские события должны быть установлены в NULL при расположении объекта?

Позволяет говорит, что у нас есть 2 объекта, Вещательная компания и Слушатель. Вещательная компания имеет событие под названием Широковещательная передача, на которую подписан Слушатель. Если Слушатель будет расположен, не отказываясь от подписки от Многоадресного события, то оно будет сохранено в памяти из-за делегата события, ссылающегося на него, что Вещательная компания содержит.

То, на предмет чего мне любопытно, - то, если Вещательная компания будет расположена без Слушателя, отказывающегося от подписки или Широковещательной передачи установки Broadcaster = пустой указатель, то Вещательная компания будет сохранена в памяти?

Я не был в состоянии определить местоположение чего-либо с твердым ответом на этот вопрос кроме одного блоггера, который полагает, что не установка в NULL события сохранит источник в памяти (найденным здесь).

Я хотел бы услышать объяснение почему или почему нет.

Спасибо.

ОБНОВЛЕНИЕ: Поток Форума, где один разработчик указывает на события, должен быть установлен в NULL, но Jon Skeet указывает, что это не необходимо, но не уточняет.

14
задан Dan Rigby 5 January 2010 в 22:35
поделиться

2 ответа

Обратите внимание, что делегаты не держат издателя в живых (они держат только цель=подписчика), поэтому никакое количество подписок не будет (само по себе) поддерживать вещателя в живых. Таким образом, с этой точки зрения, не имеет значения, будет ли она утилизирована или нет. Когда нет пунктов, ссылающихся на вещателя (и подписка на событие не имеет для этого значения), он будет иметь право на сбор.

По существу, делегат - это (список) пар MethodInfo и объект ссылок; метод вызова и объект для вызова как "arg0" (также известный как this). В нем просто нет ссылки на объект , поднимающий это событие.

Вот доказательство того, что слушатель не сохраняет источник; вы должны увидеть, что "Источник 1" собран, даже несмотря на то, что у нас все еще есть соответствующий слушатель, который подписан. Как и ожидалось, "Listener 2" собирает , а не , так как у нас всё ещё есть соответствующий вещатель:

class DataSource
{
    public DataSource(string name) { this.name = name; }
    private readonly string name;
    ~DataSource() { Console.WriteLine("Collected: " + name); }

    public event EventHandler SomeEvent;
}
class DataListener
{
    public DataListener(string name) { this.name = name; }
    private readonly string name;
    ~DataListener() { Console.WriteLine("Collected: " + name); }
    public void Subscribe(DataSource source)
    {
        source.SomeEvent += SomeMethodOnThisObject;
    }
    private void SomeMethodOnThisObject(object sender, EventArgs args) { }
}

static class Program
{
    static void Main()
    {
        DataSource source1 = new DataSource("Source 1"),
                source2 = new DataSource("Source 2");
        DataListener listener1 = new DataListener("Listener 1"),
                listener2 = new DataListener("Listener 2");
        listener1.Subscribe(source1);
        listener2.Subscribe(source2);
        // now we'll release one source and one listener, and force a collect
        source1 = null;
        listener2 = null;
        GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
        GC.WaitForPendingFinalizers(); // source 1 gets collected, ONLY

        Console.WriteLine("Done");
        Console.ReadLine();
        GC.KeepAlive(source2); // prevents collection due to optimisation
        GC.KeepAlive(listener1); // prevents collection due to optimisation
    }
}
9
ответ дан 1 December 2019 в 14:32
поделиться
[

]Нет. Цель делегатов в событии трансляции ссылается на объект "Слушатель". Это позволит сохранить объект "Слушатель". Объект "Слушатель" не имеет обратной ссылки на объект "Трансляция".[

] [

]Следите за терминологией. Удаление объекта Вещательного события ничего не делает. Это должен быть мусор, который может произойти только в том случае, если на объект не осталось ни одной ссылки. Когда это происходит, объект делегата также будет автоматически собран, так как единственной ссылкой на него является внутренний список целей делегатов, который ведется объектом делегата приватного мероприятия. Это также удаляет ссылку, которую делегат имеет на слушателя. Если нет других ссылок на слушателя, то они также будут собраны. Если это так, то он просто больше не будет получать уведомления о событиях. Короче говоря: в классе Broadcast не обязательно явно устанавливать событие на ноль.[

] [

]Не совсем то же самое в слушателе, на него ссылается событие, на которое он подписался. Если событие объявлено непригодным для бизнеса (утилизировано), но вещатель все еще находится в прямом эфире, то он должен явно удалить свою подписку на событие. Класс SystemEvents является экстремальной версией этого класса, события в нем статичны. Вы часто замечаете события, когда делегат ссылается на утилизированного слушателя.[

] [

]Большинство практичных моделей объектов пытаются обеспечить исчезновение объектов слушателя, когда утилизирует родитель. Хорошим примером может служить Windows Forms. Тогда нет необходимости явно отменять подписку на события[

].
4
ответ дан 1 December 2019 в 14:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: