DispatcherTimer在最小化/最大化/关闭窗口时暂停

时间:2013-09-11 11:40:35

标签: c# wpf

我尝试在简单的应用上解释我的问题:

我的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会暂停并保持暂停状态,直到我释放按下的按钮。

有人知道这种行为的原因吗?

3 个答案:

答案 0 :(得分:4)

只要按下其中一个按钮,就会阻止UI-Thread。因为它是DispatcherTimer,它属于Window的Dispatcher并在同一个线程中运行。因此,如果此线程被阻止,DispatcherTimer将停止运行。

您可以使用System.Timers.Timer

,只要您按住三个窗口按钮中的一个,UI就不会更新。

答案 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操作执行时依赖于队列中的其他作业及其优先级。