我在可移植库 / Windows Store 中找不到计时器。(目标为 .net 4.5 和 Windows Store,也称为 Metro)
有没有人知道如何创建某种定时事件?
我需要一种类似秒表的东西,所以这应该每秒钟或者这样刷新一次。
我在可移植库 / Windows Store 中找不到计时器。(目标为 .net 4.5 和 Windows Store,也称为 Metro)
有没有人知道如何创建某种定时事件?
我需要一种类似秒表的东西,所以这应该每秒钟或者这样刷新一次。
internal delegate void TimerCallback(object state);
internal sealed class Timer : CancellationTokenSource, IDisposable
{
internal Timer(TimerCallback callback, object state, int dueTime, int period)
{
Contract.Assert(period == -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(); }
}
2) 将您的项目降级为 .NET 4.0 和 Windows Store 应用程序,这将使您可以访问 Timer。
3) 创建一个针对 .NET 4.0 和 Windows Store 应用程序的新项目,并将需要计时器的代码放入其中。然后从 .NET 4.5 和 Windows Store 应用程序项目中引用该项目。
顺便说一下,我在 PclContrib 网站上提交了一个工作项,以添加 Timer 支持:http://pclcontrib.codeplex.com/workitem/12513。
根据David Kean提出的建议#3,这是我的hacky Timer适配器 - 将其放在针对.net 4.0的PCL库中,并从4.5引用它:
public class PCLTimer
{
private Timer _timer;
private Action _action;
public PCLTimer(Action action, TimeSpan dueTime, TimeSpan period)
{
_action = action;
_timer = new Timer(PCLTimerCallback, null, dueTime, period);
}
private void PCLTimerCallback(object state)
{
_action.Invoke();
}
public bool Change(TimeSpan dueTime, TimeSpan period)
{
return _timer.Change(dueTime, period);
}
}
然后,要使用它,您可以从您的4.5 PCL库中执行以下操作:
private void TimeEvent()
{
//place your timer callback code here
}
public void SetupTimer()
{
//set up timer to run every second
PCLTimer _pageTimer = new PCLTimer(new Action(TimeEvent), TimeSpan.FromMilliseconds(-1), TimeSpan.FromSeconds(1));
//timer starts one second from now
_pageTimer.Change(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
}
实现David Kean的建议#1,采用周期方式:
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(); }
}
我改进了Ivan Leonenko的答案,增加了一个新参数,如果周期小于回调运行时间,则将调用排队到您的回调中。并且用一个action替换了旧的TimerCallback。最后,在最后一个延迟中使用了我们的取消令牌,并使用ConfigureAwait来增加并发性,因为回调可以在任何线程上执行。
internal sealed class Timer : CancellationTokenSource
{
internal Timer(Action<object> callback, object state, int millisecondsDueTime, int millisecondsPeriod, bool waitForCallbackBeforeNextPeriod = false)
{
//Contract.Assert(period == -1, "This stub implementation only supports dueTime.");
Task.Delay(millisecondsDueTime, Token).ContinueWith(async (t, s) =>
{
var tuple = (Tuple<Action<object>, object>) s;
while (!IsCancellationRequested)
{
if (waitForCallbackBeforeNextPeriod)
tuple.Item1(tuple.Item2);
else
Task.Run(() => tuple.Item1(tuple.Item2));
await Task.Delay(millisecondsPeriod, Token).ConfigureAwait(false);
}
}, Tuple.Create(callback, state), CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Default);
}
protected override void Dispose(bool disposing)
{
if(disposing)
Cancel();
base.Dispose(disposing);
}
}
您可以使用一个PCL库创建一个计时器界面,然后使用W8S计时器在第二个W8S库中创建该接口的实现。
然后,您可以使用依赖注入将W8S库注入到PCL类中。
Observable.Timer
。由于项目已经包含了Rx,因此不需要额外引用。IDisposable timer = Observable.Timer(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1))
.Subscribe(_ => /* your useful code here */);
// unsubscribe/stop when timer is no longer needed
timer.Dispose();
System.Reactive.Linq.Observable
类在支持PCL的Rx-Linq
NuGet包中。