不使用线程池的C#中的定期任务

不使用线程池的C#中的定期任务,c#,multithreading,timer,C#,Multithreading,Timer,有没有一种方法可以在不使用线程池的情况下在C#中执行周期性任务/线程(这是我的主要要求之一) 预期情景如下所示: 周期性线程阻塞/等待计时器事件(来自系统) 当计时器过期时,系统通知线程 线程执行一些代码 线程阻塞/等待来自系统的下一个计时器事件(请注意,如果线程错过了一个或多个计时器事件,这是正常的) 我发现最接近这一点的是System.Forms.Timer,但问题是它的精度限制在55毫秒,这对我来说还不够 System.Timers.Timer似乎能够通过SynchronizingObje

有没有一种方法可以在不使用线程池的情况下在C#中执行周期性任务/线程(这是我的主要要求之一)

预期情景如下所示:

  • 周期性线程阻塞/等待计时器事件(来自系统)
  • 当计时器过期时,系统通知线程
  • 线程执行一些代码
  • 线程阻塞/等待来自系统的下一个计时器事件(请注意,如果线程错过了一个或多个计时器事件,这是正常的)
  • 我发现最接近这一点的是
    System.Forms.Timer
    ,但问题是它的精度限制在55毫秒,这对我来说还不够

    System.Timers.Timer
    似乎能够通过
    SynchronizingObject
    属性处理此问题。但是,我不确定如何根据上述场景实现
    ISynchronizeInvoke
    。我找到的用于实现
    ISynchronizeInvoke
    的所有代码示例对于处理这样一个简单的场景来说似乎太复杂了


    有没有一种方法可以像上面的场景那样在C语言中轻松实现此功能(不使用线程池),并且比
    System.Forms.Timer更准确?

    您是否尝试过简单地休眠线程

    int msecSleepTime = 25;  // number of milliseconds to sleep
    Thread.Sleep(msecSleepTime);  // sleep the current thread for the given number of milliseconds
    

    Windows计时器的默认分辨率为15.6毫秒,从其:

    Windows中的默认系统范围计时器分辨率为15.6 ms,这 表示操作系统每15.6毫秒接收一个时钟 来自系统定时器硬件的中断。当时钟中断时 激发,Windows更新计时器计时计数并检查 计划的计时器对象已过期。有些应用程序要求 计时器过期的维修频率高于每15.6毫秒一次

    它们还指出:

    应用程序可以调用timeBeginPeriod来增加计时器 决议最大分辨率为1 ms用于支持 图形动画、音频播放或视频播放。这不仅 将应用程序的计时器分辨率提高到1毫秒,但同时 影响全局系统计时器分辨率,因为Windows在 最小分辨率任何 应用程序请求。因此,如果只有一个应用程序请求 计时器分辨率为1毫秒,系统计时器设置时间间隔(同时 称为“系统计时器滴答声”)至至少1毫秒,以获取更多信息 有关详细信息,请参阅MSDN®网站上的“timeBeginPeriod函数”

    因此,如果您确实需要高分辨率计时器,您可以使用该调用来影响全局系统计时器,但要知道它会影响其工作设备的电池寿命/功耗

    此外,还有和调用可用于在.net中获得较低级别的精度,如本例所示:

    将为您提供所有计时器中最高的分辨率。如果你真的需要10毫秒或更少的分辨率,那将是唯一的选择

    如果您发现不需要多媒体计时器提供的分辨率,您将发现这将使您能够在单个线程中编写等待计时器过期的循环


    您也可以选择提供大量计时器而不需要其他计时器的资源开销的计时器,但默认情况下使用系统线程池。

    我的系统上的
    system.timers.Timer
    的最快响应w/o重新配置系统的计时器为~16毫秒。将
    Timer.Interval
    值设置为
    (int)(target interval/16)*16
    然后在剩余的时间内让线程休眠(如果您确实需要更高的准确性,那么像C#这样的解释语言不是正确的选择):

    类程序
    {
    专用静态计时器_Timer=new Timer();
    private static DateTime _last=DateTime.Now;
    专用常量int int INTENTEDINTERVAL=25;
    静态void Main(字符串[]参数)
    {
    _timer.AutoReset=false;
    _计时器间隔=(int)(预期间隔/16)*16;
    _timer.appeated+=\u timer\u appeated;
    _timer.Start();
    Console.ReadLine();
    }
    静态无效时间已过(对象发送器,ElapsedEventArgs e)
    {
    var now=DateTime.now;
    var持续时间=现在-\u最后;
    var sleep=IntendedInterval-duration.total毫秒;
    如果(0<睡眠)
    {
    系统线程线程睡眠((int)睡眠);
    }
    _timer.Start();
    现在=日期时间。现在;
    持续时间=现在-\u最后一次;
    _最后=现在;
    Console.WriteLine(duration.total毫秒.ToString());
    }
    }
    
    您需要什么级别的准确度?我将处理的最短时间约为10毫秒。您正在做什么,需要每10毫秒采取一次行动,可能会有更好的解决方案。请告诉我们您试图做什么来防止主要监视/轮询被动设备。请详细说明您是如何监视设备的ce,它使用的是什么接口,是否有一个库,或者你正在做一些类似于通过COM端口与它交谈的事情?请提供更多详细信息,以前可能使用过同一设备的人可以根据他们在尝试解决与你相同的问题时学到的知识向你提供一些建议。这不满足我的需要。假设我我需要每25毫秒运行一次线程,我的代码执行大约需要10毫秒。这意味着我下一次执行代码将在35毫秒之后,而不是25毫秒!你可以记录代码执行所需的时间,并计算出每次需要睡眠的毫秒数。如果我没有其他/更好的选择,也许我会求助于此。不是一个错误的选项-它是自包含的,不使用其他线程来运行计时,并且在调用函数的任何位置都可以工作,而不需要求助于事件驱动的状态机。
    class Program
    {
        private static Timer _timer = new Timer();
        private static DateTime _last = DateTime.Now;
        private const int IntendedInterval = 25;
    
        static void Main(string[] args)
        {
            _timer.AutoReset = false;
            _timer.Interval = (int)(IntendedInterval / 16) * 16;
            _timer.Elapsed += _timer_Elapsed;
            _timer.Start();
    
            Console.ReadLine();
        }
    
        static void _timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            var now = DateTime.Now;
            var duration = now - _last;
    
            var sleep = IntendedInterval - duration.TotalMilliseconds;
    
            if (0 < sleep )
            {
                System.Threading.Thread.Sleep(( int )sleep);
            }
    
            _timer.Start();
    
            now = DateTime.Now;
            duration = now - _last;
            _last = now;
    
            Console.WriteLine(duration.TotalMilliseconds.ToString());
        }
    }