Reputation: 323
Calling a function only after certain time interval although end user makes a request
public override void SendNotificationMessage(NotificationMessageRequest request)
{......}
this is my function which will be triggered when there is a click action.
I want this to be called only at certain time intervals say 5 mins.Although the user makes a Request before the time interval...
I am trying to have a timer to serve my purpose but the problem is every time the user clicks then timer would start again..so that how could a function be controlled by timer
PS:I can not make changes in user application where the click is made
Upvotes: 2
Views: 1955
Reputation: 8999
As a quick solution I can suggest to keep a list of delegates with the method you want to invoke on each timer tick. So on user action you just add the method you want to invoke. If the parameters must be unique for each user call, you might do something like in the following code:
// 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));
}
In the code above, you must make sure you are using the same ActionExecutor
instance where you handle the user actions. Notice the synchronization with the locks - timers usually run in separate thread than the thread adding the action. If you are speaking of a web application, then each user is running int his/her own thread, so multiple users at once will also add concurrency. Also, you may have to add appropriate error handling, as I have omitted that part for brevity.
Update
As suggested in comments, you might benefit from using a different collection than a list to hold the actions. It depends on the actual needs of your scenario.
Upvotes: 1
Reputation: 3105
First you should add a Dictionnary to your class:
Dictionnary<int, NotificationMessageRequest> _notifications
Then when a user clicks on the button, you should execute this function: (or change the one that's executed now so that it looks like this)
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);
}
}
Then call this method on your timer event:
private void SendNotifications()
{
lock(_notifications)
{
foreach(KeyValuePair<int, NotificationMessageRequest> p in _notifications)
SendNotificationMessage(p.Value);
_notifications.Clear();
}
}
If you do something more or less like that you'll have the behavior you need.
Upvotes: 2
Reputation: 13513
Create a timer and set it's interval to a proper value. Then declare a field of type System.Collections.Concurrent.ConcurrentQueue<YourMessageType>
(static if it fits) and put your message in the queue in the OnClick
.
When timer ticks call TryDequeue
and process messages.
Upvotes: 0
Reputation: 1316
I do something similar in my current system. In my case, I'm batching data requests so that rather than making multiple calls to a remote service, I can combine them into one.
This is a high level overview of the system:
I have a CollatorClass that has one method MakeRequest() Internally, CollatorClass has a Timer object that is initalised to null and a List of whatever objects hold your request details.
When MakeRequest is called: The timer is started if it's null. The details of the request are added to a list.
When the timer ticks over, the system reads the details of all requests from the list and takes the appropriate actions. (Note that you may need to make use of lock in order to make all this thread safe).
If you want, you can also pass an Action reference to be called when the data request is actually performed. Not sure if this is necessary in your case though.
Let me know if you'd like more detail.
Upvotes: 0