이번 글에서는 DispatcherTimer에 대해 알아보겠습니다. DispatcherTimer는 간단한 수준의 주기적인 작업을 할 때 사용하는 타이머입니다.
WPF에서 Thread, Task를 사용하면 주기적인 작업을 할 수 있지만 간단한 수준의 반복 작업이나, UI만 갱신하는 경우에는 Thread, Task를 사용하는 것보다 DispatcherTimer를 사용하는 것이 더 효율적 입니다. 이전 글에서도 Thread나 Task를 사용하여 UI를 갱신할 때 Dispatcher에 Post나 Invoke 함수를 사용한 것을 볼 수 있습니다.
간단하게 사용할 수 있는 타이머지만, 대신 오래 걸리는 작업을 타이머로 수행할 경우 UI가 멈추는 현상이 생길 수 도 있습니다. 간단한 예제를 통해 DispatcherTimer의 사용에 대해 알아보겠습니다.
개발
WPF 프로젝트를 생성하여 아래와 같이 .xaml 파일을 만들어줍니다.
<Window x:Class="DispatcherTimer01.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DispatcherTimer01"
mc:Ignorable="d"
Title="MainWindow"
Height="450"
Width="800">
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0"
Orientation="Horizontal">
<TextBox Text="{Binding MillSec}"
Width="100"
Margin="10"
TextAlignment="Center"/>
<Button Content="Start Timer"
Command="{Binding StartTimerCommand}"
Width="100"
Margin="10"/>
<Button Content="Stop Timer"
Command="{Binding StopTimerCommand}"
Width="100"
Margin="10"/>
</StackPanel>
<ListView Grid.Row="2"
ItemsSource="{Binding Messages}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Margin="10">
</ListView>
</Grid>
</Window>
그 다음 MainWindowViewModel.cs를 만들어 아래와 같이 만들어 줍니다.
namespace DispatcherTimer01
{
public class MainWindowViewModel : Notifier
{
public double MillSec { get; set; } = 500;
public ObservableCollection<string> Messages { get; set; } = new ObservableCollection<string>();
public Command StartTimerCommand { get; }
public Command StopTimerCommand { get; }
private DispatcherTimer _timer = new DispatcherTimer();
public MainWindowViewModel()
{
StartTimerCommand = new Command(OnStartTimerCommand, OnCanStartTimerCommand);
StopTimerCommand = new Command(OnStopTimerCommand, OnCanStopTimerCommand);
}
private void OnStartTimerCommand()
{
_timer.Interval = TimeSpan.FromMilliseconds(MillSec); // 주기
_timer.Tick += (sender, eventargs) => // Tick
{
string message = DateTime.Now.ToString("HH:mm:ss.fff");
Messages.Add(message);
};
_timer.Start(); // 타이머 시작
}
private bool OnCanStartTimerCommand()
{
return !_timer.IsEnabled; // timer가 실행 중인지
}
private void OnStopTimerCommand()
{
_timer.Stop(); // 타이머 정지
}
private bool OnCanStopTimerCommand()
{
return _timer.IsEnabled;
}
}
}
주석에도 다 써있지만 정리하면 아래와 같습니다.
- Interval : 타이머 주기. Tick 이벤트를 발생 시킬 간격
- Tick : Interval 마다 불러주는 이벤트. 주기적으로 하고 싶은 작업 입력
- IsEnabled : 타이머가 실행 중이면 true, 아니면 false
- Start : 시작 함수
- Stop : 종료 함수
위 함수를 실행하면 아래와 같이 표시됩니다.
만약 수행 작업이 오래 걸리면 아래와 같이 UI가 멈추게 됩니다. 아래는 Tick에 입력된 함수에 Thread.Sleep(1000);를 추가했을 때 나타나는 현상입니다.
github : https://github.com/3001ssw/c_sharp/tree/main/WPF/Simple_WfpApp/DispatcherTimer01

