在wp7中执行stopclock

时间:2011-12-31 11:54:18

标签: windows-phone-7 timer dispatchertimer

在我的wp7.5应用程序中,我有一个块,我需要显示一个秒钟(比如30,29,28 ...... 1,0)。我尝试了各种实现来使用DispatchTimer和Timer类来实现这一点,但它们都没有解决我的问题。

方法1: 这是我用于DispatchTimer的片段,

DispatcherTimer dt = new DispatcherTimer();
dt.Interval = new TimeSpan(0, 0, 1); // 1 second
dt.Tick += new EventHandler(dt_Tick);

for(int count=0;count<30;count++)
    dt.Start();

void dt_Tick(object sender, EventArgs e)
{
   // my UI control update here
}

在我的Tick事件实现中,我正在使用时间计数器更新UI控件。我在这里阅读了一些关于同一主题的问题,其中调度程序在某些情况下从不会因为UI线程而触发。它发生在我身上,嘀嗒事件永远不会被解雇。

方法2: 我尝试使用System.Threading.Timer类,

Timer timer = new Timer(TimerProc);

for(int count=0;count<30;count++)
    timer.Change(1000, 0);

void TimerProc(object sender)
{
   // my UI control update here
}

我的方法都没有用。我可能会问一个重复的问题,有人能指出我在代码中做错了吗?

2 个答案:

答案 0 :(得分:2)

DispatcherTimer方法调用后Start()会在间隔时间内触发Tick event,直到您在其上调用Stop()为止。因此,您不需要调用Start() 30次,但是您必须维护一个计数器,并且在Tick event处理程序中,在30个滴答之后停止计时器:

private int counter;

private void Start_Click(object sender, RoutedEventArgs e)
{
    counter = 30;
    DispatcherTimer dt = new DispatcherTimer();
    dt.Interval = new TimeSpan(0, 0, 1); // 1 second
    dt.Tick += new EventHandler(dt_Tick);
    dt.Start();
}

void dt_Tick(object sender, EventArgs e)
{
    if (counter >= 0)
    {
        timeText.Text = counter.ToString();
        counter--;
    }
    else
        ((DispatcherTimer)sender).Stop();
}

编辑:
如果DispatcherTimer的精度不够,则可以使用System.Threading.Timer,但在这种情况下,您可以在tick事件处理程序中调用Dispatcher.BeginInvoke以启用对UI线程上对象的访问:

private int counter;

private void Start_Click(object sender, RoutedEventArgs e)
{
    counter = 30;
    timeText.Text = counter.ToString();
    Timer dt = new Timer(dt_Tick);
    dt.Change(1000 /* delay to start the timer */, 1000 /* period time */);
}

private void dt_Tick(object sender)
{
    if (counter > 0)
    {
        Dispatcher.BeginInvoke(() => timeText.Text = counter.ToString());
        counter--;
    }
    else
        ((Timer) sender).Dispose();
}

答案 1 :(得分:0)

Timer tick方法不是跟踪时间的方法。为什么?有两个原因。

1 / DispatcherTimer的每个Tick之间的间隔不准确,取决于您对UI的操作。它可以是1秒,就像它可以多一点。

2 /下一个Tick在前一个tick结束后触发一秒钟。由于tick中的更新代码需要一些时间,因此它将自动落后。 例如,如果更新代码需要0.1秒,则在1秒后触发勾选,更新完成,并且在更新结束后下一个刻度为1秒,因此在计时器启动后2.1秒!

因此,您应该存储启动计时器的时间,并计算每个计时器的经过时间:

    protected DispatcherTimer Timer { get; set; }

    protected DateTime TimerStartTime { get; set; }

    private void ButtonStart_Click(object sender, RoutedEventArgs e)
    {
        this.Timer = new DispatcherTimer();
        this.Timer.Interval = TimeSpan.FromSeconds(1);
        this.Timer.Tick += this.Timer_Tick;
        this.TimerStartTime = DateTime.Now;
        this.Timer.Start();
    }

    private void Timer_Tick(object sender, EventArgs e)
    {
        int elapsedSeconds = (int)DateTime.Now.Subtract(this.TimerStartTime).TotalSeconds;

        this.TextTimer.Text = (30 - elapsedSeconds).ToString();
    }

这样,即使每个滴答之间的时间不准确,定时器也不会指示错误的时间。您甚至可以将定时器间隔缩短到500 ms或更短,以获得更精确的定时器,而无需更改Tick方法。