Temporarily pause a System.Timers.Timer in C# - c#

I'm wondering if there is some way to temporarily pause a timer and then restart it.
I have a method "DoSomething()" which can be called from within a timer event or within a different method called "Chooser()". DoSomething() should be called from the timer OR Chooser(), but it shouldn't be called twice.
The problem is that it takes some time for Chooser() to decide if it should call DoSomething(). DoSomething() shouldn't be called while Chooser() is deciding if it should also call DoSomething(). This would result in DoSomething() being called twice.
If Chooser() does choose to call DoSomething() it will disable the timer. Likewise, if the timer calls DoSomething() it will disable the code within Chooser().
I was thinking of removing the timer eventhandler at the start of Chooser() and then re-adding it at the end of Chooser(). However, this doesn't work because the timer might trigger the event while Chooser() is running, and the event will not be handled.
I don't think I can use a lock, because I only want to call DoSomething() once.
It'd be ideal if I could just pause the timer at the start of Chooser() and then start it again at the end, but I don't believe that possibility exists.
I could just add a flag, but I was wondering if there's anything better.

Set a flag under a lock that signals that DoSomething is running. Also under the lock, test whether that flag is already set. If yes, just return and do nothing.
It is not possible to reliably stop timers. Tick events can be delivered arbitrarily even after stopping the timer, even concurrently (multiple ticks at the same time).

Related

Xamarin C# cross-platform timeout timer

I need a very standard thing, a timeout timer, but it's for a PCL (Portable Class Library) Xamarin app, and there's a lot of functionality missing there. The interface I need looks something like this:
class Timeout
{
// The 'OnTimeout' event is triggered when at least numSeconds have elapsed
public delegate void VoidFunc();
public event VoidFunc OnTimeout;
// Construct the Timeout object and start the timer.
public Timeout(int numSeconds);
// Restart the timer.
public void Restart();
}
So if I construct the Timeout object at 12:00:00 as Timeout(30), then call Restart() at 12:00:29, the event fires exactly once, at 12:00:59.
Unfortunately, Xamarin cross-platform doesn't have a Timer class, so I can imagine two possibilities:
1) Construct a timer using Xamarin.Forms.Device.StartTimer when the Timeout object is constructed, and have it keep firing every second (or every quarter second or something). Every time it fires, it checks if it's supposed to trigger the event or not.
2) Start up a thread in the Timeout() constructor, have it sleep most of the time but wake up every second (or quarter second) and check if it's time to fire the event.
Neither of these options seems great to me -
1) Xamarin.Forms.Device.StartTimer works with the UI thread, so it's potentially less accurate (if the UI is busy, the event won't fire).
2) System overhead of constructing a thread, and coding overhead of making sure the thread shuts down pleasantly if the Timeout() object is destructed before the event is fired.
Both options end up wasting a tiny bit of CPU every time they wake up and realize it's not time to fire the event, certainly not a huge deal but the kind of thing I usually try to avoid doing.
Is there a more elegant solution that I'm missing?

how to handle this race condition?

in my class i use a BackgroundWorker. at some point i need to cancel the asynchronous operation that can be in progress and start another one immediately. the code follows. one thing that i am not sure about is the race condition that can occur if the worker completes right before i assign my lambda to RunWorkerCompleted event. if this happens my lambda will never get called. the comment in the code shows this place. any comments on how to handle this?
thanks
konstantin
if (this.worker.IsBusy)
{
RunWorkerCompletedEventHandler f = null;
f = (s, v) =>
{
this.RunWorkerCompleted -= f;
this.worker.RunWorkerAsync();
};
// what if worker completes right before the following statement?
this.worker.RunWorkerCompleted += f;
this.worker.CancelAsync();
}
else
{
this.worker.RunWorkerAsync();
}
As long as this code runs on the main thread then there is no race. A BGW can only complete when the RunWorkerCompleted event handler finished running. The handler cannot start running until the main thread re-enters the message loop.
There's another kind of race though, induced by the else clause. You let the BGW start without a RunWorkerCompleted event handler. Now it can complete asynchronously since it won't be blocked. Always subscribe the event, test e.Cancelled to know what happened.
You could just add the RunWorkerCompleted event handler once in the ctor and also add a bool member variable 'restart' to the class. Then you can write if(IsBusy) restart = true and in your handler you check if(restart) Run(). You can define restart as volatile to avoid race conditions in that case.
I think it is not a good practice to add and remove event handlers in your case.
Maybe i'm just not smart enough to understand your code. But in my world i would built up a Queue<Action> and fill in all jobs that have to be done.
Another thread (or BackgroundWorker) will take a look at this Queue and process all the jobs in the queue sequentially (like my answer here). Maybe this is not very elegant due to the pull-mode by using a Thread.Sleep(1) in a loop.
But this could be accomplished by creating a BindingQueue<T> that derived from Queue<T> and implements IBindingList. So you could just wait for such an event, dequeue and invoke an Action till the queue is empty and start over again.

C#: What if System.Windows.Forms.Timer interval was not enough for doing a job?

First, sorry for my bad english writing.
Suppose that we have a win form (C#) that has a timer. The timer interval has been set to 60000 milsec. So its tick event will be fired every 1 milute. Suppose we have written a method that handles tick event called Timer1_Tick. What if the job needs more that 1 minute to complete?
You've got several options, here's four I can think of:
Abandon the current job to start the new one. The big downside of this one is, of course, if the current job can't be stopped.
Wait for the current job to finish before starting the new one. This might leave you with a queue of pending jobs if each one takes more than a minute.
Don't start the new job. Let the current one finish and then wait for the next timer interval to start the new job.
Increase the interval between jobs. This is just putting off the problem.
There is no right answer. You'll have to work out what's best and works for your situation.
I'd go for #3 as my first solution.
Setup a flag that will allow you to check if the long running job has finished and only run the job if it has finished. Don't forget to reset the flag after finishing the long running job:
// field
private bool finishedWork = true;
public void Timer1_Tick(Object o, EventArgs e)
{
if (finishedWork)
{
finishedWork = false;
// do work
finishedWork = true;
}
}
Another option is to simply disable the timer between operations:
public void Timer1_Tick(Object o, EventArgs e)
{
if (finishedWork)
{
Timer1.Enabled = false;
// do work
Timer1.Enabled= true;
}
}
So set a flag when you start the job and check the flag when the timer fires. If the flag is set, do nothing in the timer handler. Remember to clear the flag when the job completes.
Are you spinning off a worker thread to do the job?
Another timer event will likely be queued, causing Timer1_Tick to be called again almost immediately after it returns. (IIRC, though, timer ticks are one of the lowest priority messages, so it'll probably handle any other messages it's had queued up to that point first, except maybe paint messages).
Note, if your function takes longer than 2 minutes to run, it's possible (read: likely) that only the latest tick will be in the queue.
If your tick processing takes longer than the timer interval, you should look into raising the interval. Either way, you should probably be doing the work in a background thread and making sure you don't start another thread if the last tick's task isn't done. Otherwise you could end up with hordes of threads all slowing each other down til your program collapses under its own weight.
Store the current state of the process in a field or property and start the process only if the state is no "running".
Disable the timer at the start of Timer1_Tick and then enable it again afterwards?
There are multiple types of Timers in .Net: One is in a System.Timers namespace, another is in System.Windows.Forms namespace and another in System.Threading.
The System.Windows.Forms.Timer control is based on UI thread and message loops, meaning it will queue the timer events and if your handler exceeds the interval, it will be called immediately after ending.
The other two timers are based on threading, and are very accurate. They will reenter you handler after the time elapsed.

What happens with timer tick after wake up from stand-by?

My C#-programm has a windows.forms.timer that fires all 24h for a background task.
During a day I put my Vista 64bit several times in stand-by mode (never switch it off).
It seems that after wake-up the timer is sort of reset.
Your timer shouldn't be set to fire every 24 hours, it should be set to fire every few seconds, or minutes, and check the time. If the time is greater than, or equal to, the time you want your task to occur, perform the task.
The Timer class is very relaxed about raising its Tick event. Internally, inside the Windows code, when the timer is due it only sets an internal flag, somewhat akin to "ought to deliver WM_TIMER". That doesn't actually happen until nothing important needs to be done by the message loop. Any message gets higher priority than WM_TIMER.
When the Windows Forms message loop calls GetMessage(), the function checks if anything needs to be returned. If the answer is "nothing" and the flag is set, it supplies WM_TIMER. And you'll get the Tick event.
A couple of consequences from that: you can never use the Tick event to keep track of time. That will inevitably fall behind. You can never get the Tick event twice in a row, it doesn't catch up. But relevant to your question: the message loop isn't pumping when the machine goes in stand-by, nothing special happens.
During standby, typically memory is stored as-is, then recalled when you wake the machine, which might cause your timer to either not tick during the stand-by, or have imprecise behavior from what you intend.

What is the best way to wait for a certain time (say 10 seconds) in C#?

I want to wait for 15 seconds, then the control should resume from the next statement.
I don't have anything else to do while waiting (Just waiting).
I know that there is Thread.Sleep(15000). What I don't know is the best method to wait? What are the limitations of this?
The code would be like this:
Method()
{
statement 1;
statement 2;
//WaitFor 15 secs here;
statement 3;
}
The disadvantage of Thread.Sleep is if this is called in your GUI thread (the thread that processes GUI events, for example, a button click handler method, or a method called from a button click handler, etc.) then you application will appear to freeze and be nonresponsive for those 15 seconds.
It would be perfectly fine if you had explicetly created a seperate thread and called Thread.Sleep in it, assuming you don't mind that thread not doing anything for 15 seconds.
The alternative would be to create a Timer and start it after stmt 2, and place stmt 3 in the Tick event handler for the timer, and also stop the timer in that handler.
This may not be a direct answer to your question. I would say check whether your process flow is better than checking whether the code is better ;-)
Are you waiting for 15 seconds just to make sure stmt2; is complete? If so then adding an handler, as soon as stmnt 2 is executed, would be a better solution (?)
You can also use a timer to wait. Thread.sleep is a bad design. We have a similar question which talks about the comparison using Thread.sleep and Timer.
Try something like the following:
void Method()
{
console.log('statement 1');
console.log('statement 2');
var timer = new System.Threading.Timer(
o => // timer callback
{
console.log('statement 2');
},
15000, // Delay
0 // Repeat-interval; 0 for no repeat
);
}
Syntax is C# 3.0, uses a lambda expression to effectively create a closure around statement #3. With this, you could use any local variables of Method. A thing to note, however, is that with this method, or any other timer-based method...the function will return immediately after creating the timer. The function won't block until the Timer executes. To achieve that, the only thing I can think of is to actually use threads and make Method() block on a signal (i.e. WaitHandle, ResetEvent, etc.) until the timed call on the other thread completes.
Thread.sleep seems a sensible thing to do if there isn't anything else to do while waiting.
It puts the thread to sleep for that time so it doesn't use any CPU resources.
You could always use a timer and then execute code after the set duration. However, if you don't actually have to do anything and just want to wait at a particular point in code, then I think Thread.Sleep(150000); is sufficient.
[Edit: spelling]
If you always want to wait for a given time, then Sleep is useful. Obviously you shouldn't do this on a thread where timely responses are expected.
Keep in mind that your thread will sleep for the duration in all cases. If for some reason you want the thread to resume sooner, you're better off using signaling or callbacks. By using either of these instead of Sleep, you will minimize the needless wait time.
void Method()
{
Statement1();
Statement2();
// Start the timer for a single 15 second shot.
// Keep a reference to it (Mytimer) so that the timer doesn't get collected as garbage
Mytimer = new System.Threading.Timer((a) =>
{
// Invoke the 3rd statement on the GUI thread
BeginInvoke(new Action(()=>{ Statement3(); }));
},
null,
15000, // 15 seconds
System.Threading.Timeout.Infinite); // No repeat
}
I don't sure 100%, but if you really need your method to return after waiting 15 sec, try following:
Method()
{
stmt1();
stmt2();
int time = DateTime.Now.Millisecond;
while (15*1000 > DateTime.Now.Millisecond - time)
{
Thread.Sleep(10)
Application.DoEvents();
}
stmt3();
}

Categories