问题描述
到目前为止,以下代码每秒都调用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。