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