Страницы

Поиск по вопросам

среда, 22 января 2020 г.

События и сборка мусора в c#

#c_sharp #winforms #события #сборщик_мусора


Начал изучать концепцию событий в c#. У меня есть следующие классы:

class CustomTimer
    {
        public delegate void DateAndTimeHandler(DateTime dateTime);

        DateAndTimeHandler dateOrTimeUpdated;

        public event DateAndTimeHandler DateOrTimeUpdated
        {
            add { lock (this) dateOrTimeUpdated += value; }
            remove { lock (this) dateOrTimeUpdated -= value; }
        }

        public CustomTimer()
        {
            InitialStartedTime = DateTime.Now;
            int num = 0;

            TimerCallback tm = new TimerCallback(ProcessTime);

            System.Threading.Timer timer = new System.Threading.Timer(tm, num, 0, 1000);

        }

        private void ProcessTime(object obj)
        {
            dateOrTimeUpdated?.Invoke(DateTime.Now);
        }

    }

    class SuperCore
    {
        public CustomTimer timer = new CustomTimer();
    }


И небольшой пример работы с этими классами в WinForms:

public partial class Form1 : Form
{
    public string StringTime
    {
        get { try { return label1.Text; } catch { return ""; }; }
        set { try { Invoke(new Action(() => { label1.Text = value; })); } catch { } }
    }

    SuperCore superCore = new SuperCore();
    public Form1()
    {
        InitializeComponent();
        superCore.timer.DateOrTimeUpdated += TimeUpdate;
    }

    void TimeUpdate(DateTime dt)
    {
        StringTime = dt.ToString();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        GC.Collect();
    }
}


Я заметил, что при сборке мусора у меня перестает обновляться время на label1, т.е.
происходит уничтожение события. Чтобы проверить это и убедиться, что так и есть, я
при нажатии на button1 вызываю сборщик мусора. Гипотеза подтвердилась.

Это приложение является просто демонстрацией проблемы.

Вопрос:
Как мне сделать так, чтобы подписка на событие сохранялась? Чтобы время обновлялось
на label1?
    


Ответы

Ответ 1



Необходимо сделать timer полем класса CustomTimer. Код класса CustomTimer будет выглядеть так: class CustomTimer { public delegate void DateAndTimeHandler(DateTime dateTime); DateAndTimeHandler dateOrTimeUpdated; public event DateAndTimeHandler DateOrTimeUpdated { add { lock (this) dateOrTimeUpdated += value; } remove { lock (this) dateOrTimeUpdated -= value; } } System.Threading.Timer timer; public CustomTimer() { int num = 0; TimerCallback tm = new TimerCallback(ProcessTime); timer = new System.Threading.Timer(tm, num, 0, 1000); } private void ProcessTime(object obj) { dateOrTimeUpdated?.Invoke(DateTime.Now); } } За ответ в комментариях на вопрос спасибо Alexander Petrov и tym32167.

Комментариев нет:

Отправить комментарий