У меня есть следующий XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:self="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Label Name="lblTime" FontSize="48" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</Window>
Код:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += timer_Tick;
timer.Start();
GC.Collect();
}
void timer_Tick(object sender, EventArgs e)
{
lblTime.Content = DateTime.Now.ToLongTimeString();
GC.Collect();
}
}
Некоторые факты, которые я знаю:
В обратном коде MainWindow не содержит ссылки на таймер. На мой взгляд, он должен быть уничтожен, и интерфейс больше не должен обновляться, так как я добавил некоторые вызовы GC.Collect. Но кажется, что он не работает, так как интерфейс все еще обновляется, и, следовательно, объект все еще жив.
Вопрос в том, что происходит? Я где-то ошибаюсь? Или я пропустил какой-то важный факт?
Редактировать 1: этот код на самом деле является примером, который я нашел в учебнике, в котором показано, как использовать DispatcherTimer. Но я подумал, что произойдет, когда начнется сбор мусора, поэтому я добавил этот GC.Collect, чтобы узнать, что произойдет. Благодаря хорошему количеству обучающих программ о.NET GC, которые я прочитал, я знаю, что вызов GC.Collect - плохая идея, и это не должно быть сделано, если только не исключительные случаи.
Класс Dispatcher поддерживает внутренний List<DispatcherTimer>
для активных таймеров. Внутренний метод Dispatcher.AddTimer() добавляет его, вызванный методом Start(). Метод RemoveTimer() вызывается методом Stop().
Это позволяет GC видеть ссылку, пока вы не остановите таймер. Который вы можете сделать только в обработчике событий, отбросив аргумент отправителя, только способ вернуть ссылку назад.
Имейте в виду, что он продолжает тикать, если вы не вызываете Stop(), даже если окно, у которого есть обработчик события для таймера, закрывается. Такой объект окна будет течь, если вы этого не сделаете, вы получите исключение ObjectDisposedException, только если вам повезет.