通过Timer c#控制函数调用

时间:2013-05-08 09:29:34

标签: c# function timer onclick

尽管最终用户发出请求,但仅在特定时间间隔后调用函数

public override void SendNotificationMessage(NotificationMessageRequest request)
    {......}

这是我的功能,当有点击动作时会触发。

我希望只在某个时间间隔(比如说5分钟)调用它。虽然用户在时间间隔之前发出请求...

我正在尝试使用计时器来达到我的目的但问题是每次用户点击然后计时器会再次启动..那么一个函数怎么可能被计时器控制

PS:我无法在点击的用户应用程序中进行更改

4 个答案:

答案 0 :(得分:1)

作为一种快速解决方案,我可以建议使用您想要在每个计时器滴答上调用的方法来保留委托列表。因此,在用户操作上,您只需添加要调用的方法。如果每个用户调用的参数必须是唯一的,您可以执行以下代码中的操作:

// 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();
    }
}

//handling user click in your application

void OnUserClick() 
{
    // built the specific notification request
    NotificationMessageRequest request = ...

    actionExecutor.AddAction(() => SendNotificationMessage(request));
}

在上面的代码中,您必须确保使用处理用户操作的相同ActionExecutor实例。注意与锁定同步 - 定时器通常在与添加动作的线程不同的线程中运行。如果您说的是Web应用程序,那么每个用户都在运行自己的线程,因此多个用户同时也会添加并发性。此外,您可能必须添加适当的错误处理,因为为了简洁我省略了该部分。


<强>更新

正如评论中所建议的那样,您可能会受益于使用与列表不同的集合来保存操作。这取决于您的方案的实际需求。

答案 1 :(得分:1)

首先,你应该在你的班级添加一个词典:

Dictionnary<int, NotificationMessageRequest> _notifications

然后,当用户点击该按钮时,您应该执行此功能:(或更改现在执行的那个,使其看起来像这样)

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();
    }
}

如果你做的事情或多或少那样,你就会有你需要的行为。

答案 2 :(得分:0)

我在我当前的系统中做了类似的事情。在我的情况下,我正在批量处理数据请求,以便不是多次调用远程服务,而是将它们合并为一个。

这是系统的高级概述:

我有一个Collat​​orClass有一个方法MakeRequest() 在内部,Collat​​orClass有一个Timer对象,该对象初始化为null,并且包含任何对象的List保存您的请求详细信息。

调用MakeRequest时: 如果计时器为空,则启动计时器。 请求的详细信息将添加到列表中。

当计时器结束时,系统会从列表中读取所有请求的详细信息并采取相应的操作。 (请注意,为了使所有这些线程安全,您可能需要使用锁。)

如果需要,还可以在实际执行数据请求时传递要调用的Action引用。不过在你的情况下不确定是否有必要。

如果您想了解更多细节,请与我们联系。

答案 3 :(得分:0)

创建一个计时器并将其间隔设置为适当的值。然后声明一个System.Collections.Concurrent.ConcurrentQueue<YourMessageType>类型的字段(如果适合则为静态字段),并将您的消息放入OnClick的队列中。

当计时器滴答时调用TryDequeue并处理消息。