给定以下代码,每x秒调用一次EventHandler

问题描述

到目前为止,以下代码每秒都调用Tick?.Invoke方法。有没有一种方法可以轻松更改代码,例如每5秒调用一次代码

private void Timer()
{
    var Now = DateTime.Now;
    int lastSecond = Now.Second;
    int lastDay = Now.Day;

    while (goOnTiming)
    {
        Now = DateTime.Now;

        if (Now.Second != lastSecond)
        {
            Tick?.Invoke(this,new TickEventArgs(Now: Now));
            lastSecond = Now.Second;
        }

        if (lastDay != Now.Day)
        {
                NewDay?.Invoke(this,new TickEventArgs(Now: Now));
                lastDay = Now.Day;
        }

    }
}

解决方法

您可以使用内置的计时器类,有很多。

您还可以将我的基类用于异步报价器:

    /// <summary>
    /// Base class for an async ticker (runs a function every period or 'tick')
    /// Adapted from <see href="https://stackoverflow.com/a/62724908/4122889"/>
    /// NOTE this class was not designed to handle UI in any way - it could,but test beforehand!
    /// </summary>
    public abstract class TickerBase
    {
        #region Properties and Fields

        private readonly ILogger<TickerBase> _logger;
        public TimeSpan Interval { get; protected set; }

        private readonly Action<ILogger,string,Exception> _tickerStarted = LoggerMessage.Define<string>(LogLevel.Trace,new EventId(0,nameof(_tickerStarted)),"Starting ticker: {0}");
        private readonly Action<ILogger,Exception> _tickerCancelled = LoggerMessage.Define<string>(LogLevel.Trace,nameof(_tickerCancelled)),"Cancellation requested: {0}");

        #endregion

        #region Construction and Destruction

        protected TickerBase(ILoggerFactory loggerFactory,TimeSpan interval)
        {
            if(interval == default) throw new ArgumentOutOfRangeException(nameof(interval),"Interval was its default value");

            _logger = loggerFactory.CreateLogger<TickerBase>() ?? throw new ArgumentNullException(nameof(loggerFactory));
            Interval = interval;
        }

        #endregion

        #region Starting

        /// <summary>
        /// Start the ticker. Don't await this function,it will run indefinitely.
        /// Be mindful of exceptions.
        /// Calling this function more than once will start more tasks and thus more tickers.
        /// </summary>
        /// <param name="ctx">cancellation token to cancel the timer</param>
        /// <returns></returns>
        public async Task StartAsync(CancellationToken ctx = default)
        {
            // Log starting and stopping of ticker(s)
            _tickerStarted(_logger,GetType().Name,null);
            ctx.Register(() => _tickerCancelled(_logger,null));

            while (true)
            {
                var delayTask = Task.Delay(Interval,ctx);
                await OnTickAsync(ctx)
                    .ConfigureAwait(false);
                await delayTask
                    .ConfigureAwait(false);

                ctx.ThrowIfCancellationRequested();
            }

            // ReSharper disable once FunctionNeverReturns Reason: as designed
        }

        protected abstract Task OnTickAsync(CancellationToken ctx = default);
    }

    #endregion
}
,

使用计时器,您可以使用系统计时器或表单计时器。下面是系统计时器的示例:

    private void CreateTimer()
    {
        var timer = new System.Threading.Timer(timerCallback);
        timer.Change(0,5000);
    }

    private void timerCallback(object state)
    {
        System.Console.WriteLine("The timer called me");
    }

顺便说一句,您的方法可能会占用大量CPU。