System.Threading.Timer无法正常工作

时间:2019-12-30 08:44:12

标签: c# timer

我注意到计时器不正确。

这是一个非常简单的C#代码:它将每1分钟打印一次当前日期/时间。 我的预期结果是:让它在下午3:30运行,那么我们将有:3:31 PM,3:32 PM,3:33 PM,...

但是有时没有收到上述结果:有时是3:31 PM,3:32 PM,3:34 PM等...

因此它丢失了1行。

谁能指出我是什么问题?

class Program
{
    static Timer m_Timer;
    static int countDown;

    static void Main(string[] args)
    {
        countDown = 60; 
        m_Timer = new Timer(TimerCallback, null, 0, 1000);

        while (true) { System.Threading.Thread.Sleep(10); };
    }

    static void TimerCallback(Object o)
    {
        countDown -= 1; 
        if (countDown <= 0)
        {
            Console.WriteLine(" ===>>>>>" + System.DateTime.Now.ToString());
            countDown = 60;
        }
        System.Threading.Thread.Sleep(10000); //long running code demo
    }
}

6 个答案:

答案 0 :(得分:2)

Windows-不是实时操作系统。因此,如果您希望计时器准确地等待1秒,那就错了。计时器可以等待更多时间的原因很多。由于timer resolution或其他高负载操作。

答案 1 :(得分:2)

System.Threading.Timer在线程池中的线程上运行。您运行回调函数,该函数每1秒在池中的一个线程上运行一次,并使用睡眠将其阻塞10秒。根据在某些时间点线程池中有多少线程,它们都可能被阻塞并等待,否则.NET应该为您分配新线程,直到您池中的线程数上限为止。

答案 2 :(得分:0)

上面的代码导致您每秒运行10秒钟的“演示”(睡眠)。您将同时运行10个工作线程。

您确定这是您要实现的目标吗?

要查看您的应用实际发生了什么,只需添加:

Console.WriteLine($"Time:{DateTime.Now.ToString("hh:mm:ss.fff tt")},Thread:{Thread.CurrentThread.ManagedThreadId},countDown:{countDown}");
在TimerCallback开头的

。您会注意到,后面的回调之间的时间间隔不完全是1000毫秒(通常是一点点)。这在非rtc操作系统中是完全正常的,并且在大多数情况下-这不是问题。请记住,该计时器并不准确。

此外,如果您尝试以这种方式使用Timer并尝试计算滴答声-这些小错误会在随后的滴答声中累积。

答案 3 :(得分:0)

如果您喜欢较新的.NET TPL语法,则可以这样编写:

using System;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            Repeat(TimeSpan.FromSeconds(10));
            Console.ReadKey();
        }

        private static void Repeat(TimeSpan period)
        {
            Task.Delay(period)
                .ContinueWith(
                    t =>
                    {
                            //Do your staff here
                            Console.WriteLine($"Time:{DateTime.Now}");
                        Repeat(period);
                    });
        }
    }

}

答案 4 :(得分:0)

我使用另一种方式,并且效果更好:计算时间之间的时差

class Program
{
    static Timer m_Timer;

    static DateTime lastRun;

    static int CHECK_POINT = 60;

    static void Main(string[] args)
    {
        lastRun = DateTime.Now;

        m_Timer = new Timer(TimerCallback, null, 0, 1000);

        while (true) { System.Threading.Thread.Sleep(10); };
    }

    static void TimerCallback(Object o)
    {
        if((DateTime.Now- lastRun).TotalSeconds >= CHECK_POINT)
        {
            lastRun = DateTime.Now;
            Console.WriteLine(" ===>>>>>" + System.DateTime.Now.ToString());
        }

        System.Threading.Thread.Sleep(10000); //long running code demo
    }
}

答案 5 :(得分:0)

我只是将这里发现的内容发布给像我这样有问题的人。 我从另一个线程找到了答案。 我使用“ HighResolutionTimer.cs”,它可以完美运行: https://gist.github.com/DraTeots/436019368d32007284f8a12f1ba0f545