wp7 中的 stopclock 实现

发布于 2024-12-23 17:11:29 字数 838 浏览 0 评论 0原文

在我的 wp7.5 应用程序中,我有一个块需要显示停止时钟(例如 30,29,28...1,0)。我尝试了使用 DispatchTimer 和 Timer 类来实现此目的的各种实现,但没有一个解决了我的问题。

方法一: 这是我用于 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 线程,调度程序在某些情况下永远不会触发。这也发生在我身上,tick 事件从未触发。

方法二: 我尝试使用 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
}

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

In my wp7.5 app, i have a block where i need to show a stopclock (say 30,29,28...1,0). I tried various implementations to achieve this using DispatchTimer and Timer classes, but none of them solved my problem.

Approach 1:
Here is the snippet i used for 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
}

in my Tick event implementation i am updating a UI control with time counter. I read some questions here on the same topic, where dispatcher tick never fires in some scenarios because of UI thread. It happened same to me, tick event never fired.

Approach 2:
I tried using System.Threading.Timer class,

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
}

None my approaches worked. I might have asking a repeated question, can anyone point me where I am doing incorrectly in the code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浮云落日 2024-12-30 17:11:29

当间隔过去时,调用 keep 的 Start() 方法之后的 DispatcherTimer 会触发 Tick 事件,直到您调用 Stop()< /代码> 就可以了。因此,您不需要调用 Start() 30 次,但必须维护一个计数器,并在 Tick 事件 处理程序中在 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();
}

编辑:< br>
如果 DispatcherTimer 的精度不够,可以使用 System.Threading.Timer,但在这种情况下,您必须在勾选事件处理程序中调用 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();
}

The DispatcherTimer after the Start() method called keep fires the Tick event when the interval elapses until when you call Stop() on it. So you don't need to call Start() 30 times but you have to maintain a counter and in the Tick event handler stop the timer after 30 ticks:

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();
}

Edit:
If the precision of the DispatcherTimer is not enough you can use System.Threading.Timer instead, but in this case you have call Dispatcher.BeginInvoke in the tick event handler to enable access for objects on the UI thread:

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();
}
删除→记忆 2024-12-30 17:11:29

计时器滴答方法不能是跟踪时间的方法。为什么?有两个原因。

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 毫秒或更短,以获得更精确的计时器,而无需更改 Tick 方法。

The Timer tick method musn't be the one to keep track of the time. Why? For two reasons.

1/ The interval between each Tick of the DispatcherTimer isn't precise, and depends on what you do with the UI. It can be 1 second, like it can be a bit more.

2/ The next Tick is triggered one second after the previous tick has ended. Since the update code inside the tick takes some time, it will automatically lag behind.
For instance, if the update code takes 0.1 second, the tick is triggered after 1 second, the update is done, and the next tick comes 1 second after the end of the update, so 2.1 second after the start of the timer!

Therefore, you should store the time when you started the Timer, and compute the elapsed time at each tick:

    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();
    }

This way, even if the time between each tick isn't precise, the timer won't indicate a false time. You can even reduce the timer interval to 500 ms or less to have a more precise timer, without changing the Tick method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文