3

我有一个函数(比如说foo()),它会不时以可变的间隔被调用。当它被调用时,它会检查时间并相应地采取行动。

我通过以下方式做到了这一点:

  • 对象在Forms.Timer需要时调用函数

  • 在函数中使用一个Diagnostics.Stopwatch对象来确定时间和决定做什么。

但是我有以下问题:当foo()被定时器的回调调用时,ElapsedMilliseconds秒表对象的值通常低于预期。例如,计时器设置为 1000,因此在foo()调用 1000 毫秒后,但在foo()正文中ElapsedMilliseconds返回 900 因此foo表现得好像经过的时间是 900(尽管它应该采取行动 A,因为实际上已经过去了 1000 毫秒,但它没有)

在 ElapsedMilliseconds 与计时器具有一致值的情况下,如何同步计时器和秒表?

编辑:一些代码

一些示例代码来解释我的问题是什么:

//foo is the function that is called by timer's callback
public void foo()
{
    //Let's see what time it is: 
    long currentTime = stopwatch.ElapsedMilliseconds();
    Item = getCurrentItem(currentTime);
    Item.Draw();
}

//this is the callback of timer
private void timer1_Tick(object sender, EventArgs e)
    {
        //set the timer for next time
        timer1.Interval = Intervals[periodIdx++];
        foo();
    }

这应该在每次间隔完成时绘制其他内容,但是由于ElapsedMilliseconds返回比计时器声称的更早的值,尽管间隔结束,但不会绘制下一项

4

2 回答 2

3

你会得到很大的不同,因为你在 1/64 秒间隔内的某个地方启动了计时器。你会得到更好的结果:

    private void StartTimers() {
        int tick = Environment.TickCount;
        while (Environment.TickCount == tick) Thread.Sleep(0);
        timer1.Enabled = true;
        stopwatch.Start();
    }

while() 循环提高了计时器在 1/64 计时器滴答开始时启动的几率。只是改善,没有保证。而且你不能对 Tick 事件延迟触发做任何事情,这完全取决于你的 UI 线程的响应能力。然而总是迟到。不要使用此代码,编写您的代码,这样您就不会关心这些计时器是否不同步。您可能必须减少计时器的 Interval 才能完成此操作,问题尚不清楚。

于 2012-01-11T16:32:05.707 回答
2

你不会用这种方法取得很大的成功。您不会在完全相同的时间启动每个计时器,也不会在完全相同的时间检查它们(在 Timer 触发它的事件和您的代码查询秒表之间有一段时间)。

如果您希望事情同步,请选择一个计时器并以此为基础。例如,如果你想使用 Forms.Timer,在你的事件处理程序中只增加一个计数器变量 - 这将告诉你你的处理程序被调用了多少次,以及 Forms.Timer 说的有效时间已通过。这是一个示例(我将由您来处理计时器滴答时间足够长以至于计数器超过 long.MaxValue 的情况)

public void foo()
{
    Item = getCurrentItem(totalElapsed);
    Item.Draw();
}

long totalElapsed = 0;

private void timer1_Tick(object sender, EventArgs e)
    {
        totalElapsed += timer1.Interval;
        //set the timer for next time
        timer1.Interval = Intervals[periodIdx++];
        foo();
    }
于 2012-01-11T15:59:18.757 回答