翼度科技»论坛 编程开发 .net 查看内容

.NET分布式Orleans - 4 - 计时器和提醒

14

主题

14

帖子

42

积分

新手上路

Rank: 1

积分
42
Timer是什么

Timer 是一种用于创建定期粒度行为的机制。
与标准的 .NET System.Threading.Timer 类相似,Orleans 的 Timer 允许在一段时间后执行特定的操作,或者在特定的时间间隔内重复执行操作。
它在分布式系统中具有重要作用,特别是在处理需要周期性执行的任务时非常有用。
Timer的注意事项


  • 计时器回调不会改变空闲激活的状态,不能用于推迟其他空闲激活的停用。
  • Grain.RegisterTimer 中传递的时间段取决于上次回调完成到下一次回调开始的时间,因此回调的频率会受到执行时间的影响。
  • 每次 asyncCallback 调用都会作为单独轮次的激活,并且不会与同一激活的其他轮次同时运行。
代码示例
  1. public class PlayerGrain : Grain, IPlayerGrain
  2. {
  3.     public Task<string> GetPlayerInfo()
  4.     {
  5.         var timer = RegisterTimer(DoSomething, null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2));
  6.         return Task.FromResult($"Player ID: {this.GetPrimaryKeyString()}");
  7.     }
  8.     private async Task DoSomething(object state)
  9.     {
  10.         // 在这里定义要执行的操作
  11.         await Task.Delay(5000);
  12.         Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} Timer Triggered: {this.GetPrimaryKeyString()}");
  13.     }
  14. }
复制代码

Reminder与Timer的区别

提醒(Reminder)是一种在 Orleans 中用于处理周期性任务的机制,与计时器类似,但具有一些重要区别:

  • 永久性触发:提醒是永久性的,除非明确取消,否则会在几乎所有情况下(包括部分或完整群集重启)继续触发。
  • 定义的持久性:提醒的定义会写入存储,但具体的事件及其时间不会。这意味着如果群集在提醒应该触发时关闭,它将错过该提醒,只会在下次提醒的触发时被重新激活。
  • 关联于Grain:提醒是与Grain关联的,而不是与任何特定激活Grain。如果提醒的触发时,粒度没有与之关联的激活,则会创建该Grain,并在下次触发时重新激活。
  • 消息传递:提醒的传递通过消息发生,受到与所有其他粒度方法相同的交错语义的约束。
  • 适用场景:提醒通常不适用于高频计时器,其周期应该以分钟、小时或天为单位。相比之下,提醒更适用于周期性任务的处理,例如定期执行清理任务或发送通知等。
如果想使用reminder,需要安装nuget包
  1. [/code]并开启reminder
  2. [code]silBuilder.UseInMemoryReminderService();
复制代码
Grain需要实现接口 IRemindable ,并使用this.RegisterOrUpdateReminder 注册reminder
  1. public interface IPlayerGrain : IGrainWithStringKey, IRemindable
  2. {
  3.     Task<string> GetPlayerInfo();
  4. }
  5. public class PlayerGrain : Grain, IPlayerGrain
  6. {
  7.     public Task<string> GetPlayerInfo()
  8.     {
  9.         this.RegisterOrUpdateReminder("myReminder", TimeSpan.FromSeconds(5), TimeSpan.FromMinutes(1));
  10.         return Task.FromResult($"Player ID: {this.GetPrimaryKeyString()}");
  11.     }
  12.     public Task ReceiveReminder(string reminderName, TickStatus status)
  13.     {
  14.         Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} Reminder Triggered: {this.GetPrimaryKeyString()}");return Task.CompletedTask;
  15.     }
  16. }
复制代码

Timer 和 Reminder 场景

使用定时器(Timer)的场景:

  • 对激活状态的要求不高:如果激活被停用或发生故障时,计时器停止运行不会产生重大影响,或者这种行为可接受。
  • 较小的分辨率:如果需要较小的时间间隔来执行任务,例如以秒或分钟为单位。
  • 计时器回调与 Grain 生命周期相关:如果需要在 Grain 的生命周期事件(如OnActivateAsync())或者调用粒度方法时启动计时器回调。
使用提醒(Reminder)的场景:

  • 持久性要求:当需要确保周期性行为在激活和任何故障中都存在时,提醒是一个更好的选择。因为提醒是永久性的,除非明确取消,否则会在几乎所有情况下继续触发。
  • 较大的时间间隔:当执行不常见的任务,例如以分钟、小时或天为单位的周期性任务时,提醒更为适合。
依赖注入创建Timer与Reminder

将 ITimerRegistry 或 IReminderRegistry 注入粒度的构造函数中,也可以创建Timer与Reminder
  1. public PlayerGrain(ITimerRegistry timerRegistry,
  2. IReminderRegistry reminderRegistry,
  3. IGrainContext grainContext)
  4. {
  5.     timerRegistry.RegisterTimer(grainContext,DoSomething,null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2));
  6.     reminderRegistry.RegisterOrUpdateReminder(grainContext.GrainId,"testreminder",TimeSpan.FromSeconds(5), TimeSpan.FromMinutes(1));
  7. }
复制代码

 

来源:https://www.cnblogs.com/chenyishi/p/18094375
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具