我根据this讨论创建了一个计时器类,但我遇到了问题,经过的事件只发生一次。 较小的问题:如果_timer不必在每次调用Start()时都被实例化,那将是一件好事。
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics.Contracts;
namespace JellystonePark.Model
{
internal delegate void TimerCallback(object state);
internal sealed class Timer : CancellationTokenSource, IDisposable
{
internal Timer(TimerCallback callback, object state, TimeSpan dueTime, TimeSpan period)
{
Contract.Assert(period == TimeSpan.FromMilliseconds(-1), "This stub implementation only supports dueTime.");
Task.Delay(dueTime, Token).ContinueWith((t, s) =>
{
var tuple = (Tuple<TimerCallback, object>)s;
tuple.Item1(tuple.Item2);
}, Tuple.Create(callback, state), CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion,
TaskScheduler.Default);
}
public new void Dispose() { base.Cancel(); }
}
public class PCLTimer
{
private Timer _timer;
private TimeSpan _interval;
/// <summary>
/// Interval between signals in milliseconds.
/// </summary>
public double Interval
{
get { return _interval.TotalMilliseconds; }
set { _interval = TimeSpan.FromMilliseconds(value); Stop(); Start(); }
}
/// <summary>
/// True if PCLTimer is running, false if not.
/// </summary>
public bool Enabled
{
get { return null != _timer; }
set { if (value) Start(); else Stop(); }
}
/// <summary>
/// Occurs when the specified time has elapsed and the PCLTimer is enabled.
/// </summary>
public event EventHandler Elapsed;
/// <summary>
/// Starts the PCLTimer.
/// </summary>
public void Start()
{
if (0 == _interval.TotalMilliseconds)
throw new InvalidOperationException("Set Elapsed property before calling PCLTimer.Start().");
_timer = new Timer(OnElapsed, null, _interval, _interval);
}
/// <summary>
/// Stops the PCLTimer.
/// </summary>
public void Stop()
{
_timer.Dispose();
}
/// <summary>
/// Releases all resources.
/// </summary>
public void Dispose()
{
_timer.Dispose();
}
/// <summary>
/// Invokes Elapsed event.
/// </summary>
/// <param name="state"></param>
private void OnElapsed(object state)
{
if (null != _timer && null != Elapsed)
Elapsed(this, EventArgs.Empty);
}
}
}
答案 0 :(得分:2)
如果您对使用任务实现Timer感兴趣,可以尝试以下代码:
public delegate void TimerCallback(object state);
public sealed class Timer : CancellationTokenSource, IDisposable
{
public Timer(TimerCallback callback, object state, int dueTime, int period)
{
Task.Delay(dueTime, Token).ContinueWith(async (t, s) =>
{
var tuple = (Tuple<TimerCallback, object>) s;
while (true)
{
if (IsCancellationRequested)
break;
Task.Run(() => tuple.Item1(tuple.Item2));
await Task.Delay(period);
}
}, Tuple.Create(callback, state), CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion,
TaskScheduler.Default);
}
public new void Dispose() { base.Cancel(); }
}
如前所述,您可以引入对某些接口的依赖,并要求用户为您提供特定的计时器实现。