#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.
Комментариев нет:
Отправить комментарий