我尝试在简单的应用上解释我的问题:
我的MainWindow只有一个TextBlock。属性TextBlock的文本绑定到我的类CTimer的属性Seconds。在MainWindow中,我还有一个DispatcherTimer每秒做一个简单的事情 - 增加我的对象的Seconds属性。
MainWindow.xaml:
<Window x:Class="Try.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBlock Name="txtTime" Text="{Binding Seconds}" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="16" FontWeight="Bold"/>
</Grid>
</Window>
MainWindow.xaml.cs:
public partial class MainWindow : Window
{
private CTimer timer = new CTimer();
private DispatcherTimer ticker = new DispatcherTimer();
public MainWindow()
{
InitializeComponent();
ticker.Tick += AddSeconds;
ticker.Interval = TimeSpan.FromSeconds(1);
txtTime.DataContext = timer;
ticker.Start();
}
public void AddSeconds(object sender, EventArgs e)
{
timer.Seconds++;
}
}
CTimer.cs:
public class CTimer:INotifyPropertyChanged
{
private int seconds = 0;
public int Seconds
{
get { return seconds; }
set
{
seconds = value;
OnPropertyChanged("Seconds");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
我的问题 - 当我按下三个窗口按钮(最小/最大/关闭)中的任何一个并按住它时,DispatcherTimer会暂停并保持暂停状态,直到我释放按下的按钮。
有人知道这种行为的原因吗?
答案 0 :(得分:4)
只要按下其中一个按钮,就会阻止UI-Thread。因为它是DispatcherTimer,它属于Window的Dispatcher并在同一个线程中运行。因此,如果此线程被阻止,DispatcherTimer将停止运行。
您可以使用System.Timers.Timer
。
答案 1 :(得分:2)
这是设计的。 DispatcherTimer只能在执行WPF调度程序循环时触发其Tick事件。当Windows启动自己的模态调度程序循环时,它不会用于例如调整窗口大小时。
没有Timer类能够为您提供保证以请求的间隔运行的回调。包括异步计时器,它可以更好地完成它,因为它们可以在线程池线程上触发回调,因此不受UI线程中发生的任何事情的影响。但这也无法解决您的问题,您仍需要调度程序在UI线程上调用UIElement更新。
所以最基本的错误是你依靠DispatcherTimer来保持时间。它不是为此而做的。 Environment.TickCount和DateTime.UtcNow保留时间。仅使用DispatcherTimer更新显示的值,从其中一个属性计算实际值。
答案 2 :(得分:1)
原因很简单,因为当单击按钮时,您正在使用运行计时器的线程,并且线程一次只能执行一项操作。有关详细信息,请查看MSDN上的DispatcherTimer Class
页面。
从链接页面:
DispatcherTimer在每个Dispatcher循环的顶部重新评估。
不保证定时器在时间间隔发生时准确执行,但保证在时间间隔发生之前不执行定时器。这是因为DispatcherTimer操作与其他操作一样放在Dispatcher队列中。 DispatcherTimer操作执行时依赖于队列中的其他作业及其优先级。