C#-如何使精确计时器在多线程环境中工作?

时间:2018-08-20 15:46:19

标签: c# dll timer

您好,有人可以在Accurate Timer类中为我提供帮助吗?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("AccuTimer Test......");
            new Thread(delegate () {
                var a = new RunInTreadUseAccutimer(500, 0, "AccuTimer 1");
            }).Start();
            new Thread(delegate () {
                var b = new RunInTreadUseAccutimer(5000, 4900, "AccuTimer 2");
            }).Start();
            new Thread(delegate () {
                var c = new RunInTreadUseTreadSleep(500, "Thread Sleep 1");
            }).Start();
            new Thread(delegate () {
                var d = new RunInTreadUseTreadSleep(5000, "Thread Sleep 2");
            }).Start();
            Console.Read();
        }
    }

    public class RunInTreadUseAccutimer
    {
        private readonly int _interval;
        private readonly int _interval2;
        private readonly string _name;
        private AccuTimer _timer;

        public RunInTreadUseAccutimer(int interval, int interval2, string name)
        {
            _interval = interval;
            _interval2 = interval2;
            _name = name;
            _timer = new AccuTimer(this, "Go", _interval);
        }

        public void Go()
        {
            Console.WriteLine($"{DateTime.UtcNow:ddd d MMM yyyy HH:mm:ss.ffff} - Name: {_name} - Interval: {_interval}");
            Thread.Sleep(_interval2);
        }
    }

    public class RunInTreadUseTreadSleep
    {
        private readonly int _interval;
        private readonly string _name;

        public RunInTreadUseTreadSleep(int interval, string name)
        {
            _interval = interval;
            _name = name;
            Go();
        }

        public void Go()
        {
            while (true)
            {
                Thread.Sleep(_interval);
                Console.WriteLine($"{DateTime.UtcNow:ddd d MMM yyyy HH:mm:ss.ffff} - Name: {_name} - Interval: {_interval}");
            }
        }
    }

    public class AccuTimer
    {
        private delegate void TimerEventDel(int id, int msg, IntPtr user, int dw1, int dw2);
        private const int TIME_PERIODIC = 1;
        private const int EVENT_TYPE = TIME_PERIODIC;// + 0x100;  // TIME_KILL_SYNCHRONOUS causes a hang ?!
        [DllImport("winmm.dll")]
        private static extern int timeBeginPeriod(int msec);
        [DllImport("winmm.dll")]
        private static extern int timeEndPeriod(int msec);
        [DllImport("winmm.dll")]
        private static extern int timeSetEvent(int delay, int resolution, TimerEventDel handler, IntPtr user, int eventType);
        [DllImport("winmm.dll")]
        private static extern int timeKillEvent(int id);

        private readonly string _method;
        private readonly int _accuTimerId;
        private readonly dynamic _className;
        // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
        private readonly TimerEventDel _accuHandler;  // NOTE: declare at class scope so garbage collector doesn't release it!!!

        public AccuTimer(dynamic className, string method, int delay)
        {
            _method = method;
            _className = className;
            timeBeginPeriod(1);
            _accuHandler = new TimerEventDel(TimerCallback);
            _accuTimerId = timeSetEvent(delay, 0, _accuHandler, IntPtr.Zero, EVENT_TYPE);
        }

        public void Stop()
        {
            int err = timeKillEvent(_accuTimerId);
            timeEndPeriod(1);
            Thread.Sleep(100);// Ensure callbacks are drained
        }

        private void TimerCallback(int id, int msg, IntPtr user, int dw1, int dw2)
        {
            if (_accuTimerId != 0)
            {
                var methodInfo = _className.GetType().GetMethod(_method);
                if (methodInfo != null)
                    methodInfo.Invoke(_className, null);
            }
        }
    }
}

我在这里找到了毫秒级的精确计时器:Most accurate timer in .NET?关于Stackoverflow,我对此计时器的精确度和性能感到非常满意。但是当我尝试在不同线程中同时使用两个计时器时,我现在遇到了问题。如果我阻塞了其中一个踏板,则它将阻塞另一个线程上的计时器。...如果您运行上述程序,则会被破坏...

我如何修改此类以适应踩踏/线程安全?

0 个答案:

没有答案