C# 通过定时器c控制函数调用#
尽管最终用户发出请求,但仅在特定时间间隔后调用函数C# 通过定时器c控制函数调用#,c#,function,timer,onclick,C#,Function,Timer,Onclick,尽管最终用户发出请求,但仅在特定时间间隔后调用函数 public override void SendNotificationMessage(NotificationMessageRequest request) {......} 这是我的功能,当有点击动作时会触发 我希望只在特定的时间间隔(比如5分钟)调用它。尽管用户在该时间间隔之前发出请求 我试图用一个计时器来达到我的目的,但问题是每次用户点击时,计时器都会重新启动。那么,一个函数怎么能由计时器控制呢 PS:我不能在用户应用程序中
public override void SendNotificationMessage(NotificationMessageRequest request)
{......}
这是我的功能,当有点击动作时会触发
我希望只在特定的时间间隔(比如5分钟)调用它。尽管用户在该时间间隔之前发出请求
我试图用一个计时器来达到我的目的,但问题是每次用户点击时,计时器都会重新启动。那么,一个函数怎么能由计时器控制呢
PS:我不能在用户应用程序中进行更改,在用户应用程序中进行单击是一种快速解决方案,我可以建议保留一个代理列表,其中包含您希望在每个计时器计时时调用的方法。因此,在用户操作中,您只需添加要调用的方法。如果每个用户调用的参数必须是唯一的,则可以在以下代码中执行类似操作:
// This is the class handling the timer ticks
public class ActionExecutor : IDisposable
{
private Timer timer;
private IList<Action> actionsList = new List<Action>();
public ActionExecutor()
{
// choose the interval as suits you best, or use
// constructor argument
timer = new Timer(1000);
timer.Elapsed += OnTimerTick;
timer.AutoReset = true;
timer.Start();
}
void OnTimerTick(object sender, ElapsedEventArgs)
{
lock(actionsList)
{
foreach(Action a in actionsList)
{
a();
}
actionsList.Clear();
}
}
public void AddAction(Action a)
{
lock(actionList)
{
actionList.Add(a);
}
}
public void Dispose()
{
// we must stop the timer when we are over
if (timer != null)
{
timer.Stop();
}
if (actionList != null)
{
actionList.Clear();
}
}
~ActionExecutor()
{
Dispose();
}
}
在上面的代码中,必须确保您使用的是处理用户操作的相同的ActionExecutor
实例。请注意与锁的同步-计时器通常在单独的线程中运行,而不是在添加操作的线程中运行。如果您说的是web应用程序,那么每个用户都在自己的线程中运行,因此多个用户同时也会增加并发性。此外,您可能需要添加适当的错误处理,因为为了简洁起见,我省略了该部分
更新
正如注释中所建议的,使用不同于列表的集合来保存操作可能会使您受益。这取决于您场景的实际需要。我在当前系统中也做了类似的事情。在我的例子中,我对数据请求进行批处理,这样就可以将它们组合成一个,而不是对远程服务进行多次调用 这是系统的高级概述: 我有一个CollatorClass,它有一个方法MakeRequest() 在内部,CollatorClass有一个初始化为null的计时器对象和一个包含请求详细信息的对象列表 调用MakeRequest时: 如果计时器为空,则启动计时器。 请求的详细信息将添加到列表中 当计时器计时结束时,系统从列表中读取所有请求的详细信息,并采取适当的操作。 (请注意,您可能需要使用lock以确保所有线程安全) 如果需要,还可以传递一个操作引用,以便在实际执行数据请求时调用。不过,我不确定这在您的情况下是否有必要
如果你想了解更多细节,请告诉我。首先,你应该在课堂上添加一个词汇:
Dictionnary<int, NotificationMessageRequest> _notifications
然后在计时器事件上调用此方法:
private void SendNotifications()
{
lock(_notifications)
{
foreach(KeyValuePair<int, NotificationMessageRequest> p in _notifications)
SendNotificationMessage(p.Value);
_notifications.Clear();
}
}
private void SendNotifications()
{
锁定(_通知)
{
foreach(KeyValuePair p in_通知)
SendNotificationMessage(p.值);
_通知。清除();
}
}
如果你做了类似的事情,你就会有你需要的行为。创建一个计时器,并将其间隔设置为一个合适的值。然后声明一个类型为
System.Collections.Concurrent.ConcurrentQueue
(如果合适,则为静态)的字段,并将消息放入OnClick
中的队列中
当计时器滴答声调用
TryDequeue
并处理消息时。您是否可以发布更多的SO示例代码以进行解密?您的应用程序中是否有多个用户可以调用此函数?是的,将有多个用户,并且一旦调用此函数,将向其他人发送一些通知……因此,为了防止垃圾邮件,我很抱歉寻找此函数的及时调用我不认为操作的列表
就足够了,它应该是一个字典
或基于用户ID的其他东西。否则,用户可以计划多次执行相同的操作,而不必注意it@ppetrov是的,如果OP希望避免重复或以其他方式管理添加的项目,这可能是一种更好的方法。我选择了List
以允许按添加的顺序执行操作。这并不能解决我的问题,因为每次单击按钮时,只会调用同一个函数,对于该函数,我需要一些计时器,并且您的代码只能在有多个计时器时使用functions@Raghu,我跳过了那部分,因为我想强调动作的存储和处理。我已经对代码进行了编辑,添加了一个更完整的带有计时器的ActionExecutor
。@IvayloSlavov当然我很抱歉!没想到,我被我的循环场景卡住了哈哈!我将删除相关注释,因为它们对问题没有用处我不会批处理请求…我将阻止请求,因此只会执行及时调用,其他调用将不会执行。您可以通过更改MakeRequest方法来实现这一点,如果计时器为空,则仅将请求添加到列表中。(哦,别忘了在timer tick方法的末尾将timer对象设为null。)让我为一个用户执行此操作…我有一个用户,他可能会发出多个请求..首先让我解决这个问题,将来可能会有多个用户…单用户调用onClick()因此,该函数执行一次,即使他再次调用onClick(),也不应该调用该函数。这将适用于您想要的所有用户。但是通过这种方式,您的函数只会每五分钟执行一次(例如)。如果用户单击按钮,计时器还没有勾选,它将在稍后执行该功能+1收集NotificationMessageRequest
对于OP来说是一种更简单、可能更好的方法。是的,我尝试过,但每次都是onClick()因此,我阻止函数的目的将无法实现。为什么要重新启动计时器?如果这是一个web应用程序,则将其设置为静态字段(显然,您的勾号处理程序也将是静态的)。您是否每次调用OnClick时都创建计时器?不,我正在为每个OnClick创建计时器,但我
private void PlanNotification(NotificationMessageRequest request, int userId)
{
// or grab the userId from where you can
lock(_notifications) // if needed ?
{
if (_notifications.Contains(userId)) return;
_notifications.Add(userId, request);
}
}
private void SendNotifications()
{
lock(_notifications)
{
foreach(KeyValuePair<int, NotificationMessageRequest> p in _notifications)
SendNotificationMessage(p.Value);
_notifications.Clear();
}
}