Orleans运行时提供两种机制来让开发者可以指定grain的一些周期性行为,叫做定时器和提醒器。
定时器 用来创建周期性的不需要跨越多个激活(grain的实例)的grain行为。它本质上是一种.NET标准。NET System.Threading.Timer类。此外,在grain激活中保证以单线程执行。
每一个激活可能有0个或者多与它有关的定时器。每个定时器例程在与它相关的运行时上下文中执行。
使用Grain.RegisterTimer方法启动一个定时器,返回IDisposable引用:
protected IDisposable RegisterTimer(Func<object, Task> asyncCallback, object state, TimeSpan dueTime, TimeSpan period)
通过析构来取消一个定时器。
如果激活已经注销了或者当错误发生导致了它的silo崩溃,定时器将停止触发。
重要考量
当激活集合已经启用,一个定时器的回掉函数执行不会把激活的状态从闲置变为在使用。这意味着一个定时器不能用来阻止限制的激活注销。 传递给Grain.RegisterTimer的period是从asyncCallback返回的Task被求值得那一刻到下一个asyncCallback被调用经过的时间。这样不光使得对asyncCallback的成功调用不可能重叠并且完成asyncCallback花费的时间会影响asyncCallback调用的频率。 每一个asyncCallback的调用在单独的回合被传递给一个激活并且永远不会在同一个激活中与跟其他回合并发执行。然而请注意,asyncCallback调用不会被当作信息传递并且因此不受消息交错语义的影响。这表示在grain的消息消方面看,asyncCallback的调用应该被当作表现的像运行在一个可重入的grain。
提醒器类似定时器,但是有一些重要的不同:
提醒器的持久化依赖存储功能。你必须在提醒器子系统运转之前指定提醒器使用的后端存储。提醒器功能由服务端配置中的SystemStore元素控制。可以使用Azure Table和SQL server作为存储。
<SystemStore SystemStoreType="AzureTable" /> OR
<SystemStore SystemStoreType="SqlServer" />
如果你仅仅是想使用一个占位的提醒器实现来工作不需要设置Azure账户或者SQL数据库,通过添加这个元素到配置文件中(在’Globals’下),能让你得到一个提醒器系统的开发时使用的实现。
<ReminderService ReminderServiceType="ReminderTableGrain"/>
一个使用提醒器的grain必须实现IRemindable.RecieveReminder方法。
Task IRemindable.ReceiveReminder(string reminderName, TickStatus status)
{
Console.WriteLine("Thanks for reminding me-- I almost forgot!");
return TaskDone.Done;
}
使用返回一个IOrleansReminder对象的Grain.RegisterOrUpdateReminder方法来启动一个提醒器。
protected Task<IOrleansReminder> RegisterOrUpdateReminder(string reminderName, TimeSpan dueTime, TimeSpan period)
因为提醒器独立于任何单个激活的生存时间,所以他们必须显式地取消(而不是被析构)。你可以通过调用Grain.UnregisterReminder取消一个提醒器。
protected Task UnregisterReminder(IOrleansReminder reminder)
reminder是Grain.RegisterOrUpdateReminder返回的处理对象。
IOrleansReminder的实例不保证在激活的寿命之前有效。如果你想有效识别一个提醒器,使用一个包含提醒器名字的字符串。
如果你只有提醒器的名字并且需要相应的IOrleansReminder实例,调用Grain.GetReminder方法:
protected Task<IOrleansReminder> GetReminder(string reminderName)
我们建议你在以下情况下使用定时器:
Grain.OnActivateAsync或者grain方法被调用的时候被启动。我们建议你在以下情况使用提醒器:
你可能考虑组合使用定时器和提醒器来完成你的目的。例如:如果你需要一个小周期的并且不受激活影响的定时器,你可以使用一个每五分钟运行的提醒器,目的是唤醒一个grain来重启可能在注销时已经丢失的本地定时器。