Rob*_*ous 5 c# asp.net web-applications timer signalr
假设您有一个应用程序,允许用户监视他们的所有牛奶壶.所有牛奶壶都会在某个时候到期.
我想要监控所有的牛奶壶,看看他们的"isExpired"属性是真是假.
我应该每隔一段时间用一些像timerjob这样的东西迭代所有的水罐来更新属性吗?如果我想要一个水壶过期后立即反馈怎么办?在.NET/C#世界中,我可以使用哪些工具来实现这种便宜/高效的工具?
一旦jug过期,我最终会使用signalR之类的东西将通知推送到网络客户端 - 我只是不知道如何确定一个水壶过期而不经常迭代所有东西.
==
原谅我把两个问题塞进去,但显然当用户正在观看水壶时发送通知是很重要的.那么也许只有在用户的会话处于活动状态时运行的timerjob才有效?这里的任何提示/推荐阅读都会很棒.
如果您希望在水壶过期时立即收到通知,您可以执行以下操作:
Scan the list of jugs and find the one with the earliest expiration date
Set a timer to expire at that date/time.
When the timer expires, remove that jug from the list.
Scan the list of jugs to find any other jugs that expire at this time.
Send notifications for all the expired jugs.
Go to step 1.
Run Code Online (Sandbox Code Playgroud)
该算法存在一些问题:
您可以通过对列表进行排序来免除扫描列表的麻烦。然后您就会知道最早的到期日期始终位于列表的顶部。当您添加新水壶时,只需在到期时间之前插入即可。您可以使用二分搜索来确定插入位置。
或者,您可以使用优先级队列(二进制堆或跳跃列表)按到期日期存储罐子。您使用哪种数据结构取决于您拥有的项目数量以及更新项目的频率。罐子越多,访问它们的频率越高,您就越应该关注高效的数据结构。
这种方法的优点在于,您的计时器仅在您需要使罐子过期时才会滴答作响。你从不进行民意调查。
在 .NET 中创建这样的一次性计时器很简单:
TimeSpan expirationDelay = jug.ExpirationDateTime - DateTime.Now;
System.Threading.Timer jugTimer = new System.Threading.Timer(
JugExpirationCallback, null, expirationDelay, TimeSpan.FromMilliseconds(-1));
Run Code Online (Sandbox Code Playgroud)
构造函数的最后一个参数告诉它不是一个周期性计时器,而是触发一次并退出。然后,您可以通过调用计时器的方法来更新下一个壶的计时器Change。
请注意,计算时expirationDelay不考虑夏令时。如果您想这样做,您需要DateTime在计算之前将这些值转换为 UTC。或者,您可以使用WaitableTimer来执行此操作。本文末尾有一个 WaitableTimer 源代码的链接。
我怀疑,在您发表评论后,您想通知登录用户罐子即将过期。我可能会选择一个集合(列表或优先级队列),其中为每个登录用户包含一个罐子:最早过期的一个。当用户的项目过期时,您可以执行数据库查询来获取该用户下一个将过期的项目,并将其添加到列表中。当然,这取决于您期望拥有多少用户、每个用户拥有多少罐以及物品过期的频率。
您可以尝试将它们全部保留在内存中,但随后您必须管理更新。也就是说,如果数据库更新,您也必须更新内存中的表示。如果每个用户只保留一个,那么这个问题就会大大简化。而且它需要的内存也少得多。
无论您决定如何填充列表,基本思想都保持不变:创建一个计时器,配置为在最早的项目到期时触发。当每一项到期时,重置下一项的计时器。
您决定如何将项目添加到列表中“只是一个细节”。我无法提出更具体的建议,因为我对您的申请了解不够。
| 归档时间: |
|
| 查看次数: |
361 次 |
| 最近记录: |