With reference to this quote from MSDN about the System.Timers.Timer:
The Timer.Elapsed event is raised on a
ThreadPool thread, so the
event-handling method might run on one
thread at the same time that a call to
the Timer.Stop method runs on another
thread. This might result in the
Elapsed event being raised after the
Stop method is called. This race
condition cannot be prevented simply
by comparing the SignalTime property
with the time when the Stop method is
called, because the event-handling
method might already be executing when
the Stop method is called, or might
begin executing between the moment
when the Stop method is called and the
moment when the stop time is saved. If
it is critical to prevent the thread
that calls the Stop method from
proceeding while the event-handling
method is still executing, use a more
robust synchronization mechanism such
as the Monitor class or the
CompareExchange method. Code that uses
the CompareExchange method can be
found in the example for the
Timer.Stop method.
Can anyone give an example of a "robust synchronization mechanism such as the Monitor class" to explain what this means exactly?
I am thinking it means use a lock somehow, but I am unsure how you would implement that.
Stopping a System.Timers.Timer reliably is indeed a major effort. The most serious problem is that the threadpool threads that it uses to call the Elapsed event can back up due to the threadpool scheduler algorithm. Having a couple of backed-up calls isn't unusual, having hundreds is technically possible.
You'll need two synchronizations, one to ensure you stop the timer only when no Elapsed event handler is running, another to ensure that these backed-up TP threads don't do any harm. Like this:
System.Timers.Timer timer = new System.Timers.Timer();
object locker = new object();
ManualResetEvent timerDead = new ManualResetEvent(false);
private void Timer_Elapsed(object sender, ElapsedEventArgs e) {
lock (locker) {
if (timerDead.WaitOne(0)) return;
// etc...
}
}
private void StopTimer() {
lock (locker) {
timerDead.Set();
timer.Stop();
}
}
Consider setting the AutoReset property to false. That's brittle another way, the Elapsed event gets called from an internal .NET method that catches Exception. Very nasty, your timer code stops running without any diagnostic at all. I don't know the history, but there must have been another team at MSFT that huffed and puffed at this mess and wrote System.Threading.Timer. Highly recommended.
That is what it is suggesting.
Monitor is the class that's used by the C# compiler for a lock statement.
That being said, the above is only a problem if it is an issue in your situation. The entire statement basically translates to "You could get a timer event that happens right after you call Stop(). If this is a problem, you'll need to deal with it." Depending on what your timer is doing, it may be an issue, or it may not.
If it's a problem, the Timer.Stop page shows a robust way (using Interlocked.CompareExchange) to handle this. Just copy the code from the sample and modify as necessary.
Try:
lock(timer) {
timer.Stop();
}
Here is a very simple way to prevent this race condition from occurring:
private object _lock = new object();
private Timer _timer; // init somewhere else
public void StopTheTimer()
{
lock (_lock)
{
_timer.Stop();
}
}
void elapsed(...)
{
lock (_lock)
{
if (_timer.Enabled) // prevent event after Stop() is called
{
// do whatever you do in the timer event
}
}
}
Seems timer is not thread safe. You must keep all calls to it in sync via locking. lock(object){} is actually just short hand for a simple monitor call.
Related
I need to do some operations on a certain interval (e.g. from 5 to 5 minutes in a loop) but need to be able to fully stop the thing whenever I want (on push of a button).
I was thinking into using a Timer class but events might fire even after the timer is stopped.
How can I have some code running on a timer and still be able to immediately bring everything to a complete stop?
Just so I am properly understood: By complete stop I mean that events stop and I can dispose of objects like the timer itself etc. I am not asking how to avoid having side effects from unexpected events that are fired after the timer is stopped!
Answer to this question depends a lot on a type of your operations.
Best scenario is to run a thread with a loop and listen to abort event.
static AutoResetEvent abort = new AutoResetEvent();
Thread worker = new Thread(WorkerThread);
void MainThread()
{
worker.Start();
Thread.Sleep(30000);
abort.Set();
}
void WorkerThread()
{
while(true)
{
if(abort.WaitOne(5000)) return;
// DO YOUR JOB
}
}
When you call abort.Set() from another thread, this one will exit.
But if your code is long running, you won't be able to exit until job is done.
To exit immediately you will have to abort thread, but this is not too wise because of resource consumption.
Alternatively, if your operation is long running (let's say you are going through long array), you can check "abort" event state from time to time (every iteration of loop, for example) like this abort.WaitOne(0).
The race condition with the timer is unavoidable since, as you say, the callbacks are executed from the thread pool. However, I believe you can safely dispose the timer even while it's still executing the events. An option which might help is if you consider using the System.Threading.Timer instead of System.Timers.Timer, for which you can call Timer.Dispose(WaitHandle) if you need to have a way to know when the timer events have finished executing. This will prevent race conditions for the cases where you also need to dispose of some other resource - a resource that the event consumer function will attempt to use.
As for the "immediate" requirement, the most immediate would probably be something that uses a synchronization primitive of sorts to stop execution. For example consider this:
static System.Timers.Timer timer;
static void Main(string[] args)
{
var cancelSource = new CancellationTokenSource();
timer = new System.Timers.Timer(200);
timer.Elapsed += new SomeTimerConsumer(cancelSource.Token).timer_Elapsed;
timer.Start();
// Let it run for a while
Thread.Sleep(5000);
// Stop "immediately"
cancelSource.Cancel(); // Tell running events to finish ASAP
lock (timer)
timer.Dispose();
}
class SomeTimerConsumer
{
private CancellationToken cancelTimer;
public SomeTimerConsumer(CancellationToken cancelTimer)
{
this.cancelTimer = cancelTimer;
}
public void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
lock (timer)
{
// Do some potentially long operation, that respects cancellation requests
if (cancelTimer.IsCancellationRequested)
return;
// More stuff here
}
}
}
This is a toy example, but it illustrates my point. The 3 lines that do the "stop immediately" have the following features:
By the time the Dispose call returns, none of the // More stuff here code will ever execute again.
None of the // More stuff here code can execute while the timer is being disposed, because of the lock.
The previous 2 features require the lock, but they prevent the timer from stopping "immediately" because on entering the lock it needs to wait for all timer events calls to finish if they have started. For this reason I added in the cancellation as the fastest way to abort the currently executing events while still guaranteeing that they won't be executing during timer dispose.
Note: if you need multiple timer events to execute simultaneously, consider using a ReaderWriterLockSlim instead of a monitor.
I'd consider one of these two options:
Put a safety check in the events that you need to execute. Something like a database flag. So even if the Timer fails to stop the event will bail out when the safety check fails.
Use something like Quartz.Net for scheduling. This is really heavy handed but it'll do what you want.
Specifically, if you create an instance of a Timer in the local scope, and then return from that scope:
1) Will the timer still execute?
2) When would it be garbage collected?
I offer these two scenarios:
Timer timer = new Timer(new TimerCallback((state) => { doSomething(); }));
timer.Change((int)TimeSpan.FromSeconds(30), (int)TimeSpan.FromSeconds(30));
return;
And
Timer timer = new Timer(new TimerCallback((state) => { doSomething(); }));
timer.Change((int)TimeSpan.FromSeconds(30), Timeout.Infinite);
return;
The TimerCallback has a reference to the method DoSomething(), and therefore (in your example) to this but there is no live reference going the other way so it should get collected...eventually
The timer might or might not execute, depends on whether garbage collection runs before the time executes. This is why it's good practice to keep a reference to the timer somewhere other than on the stack.
Note that this is not always problematic; for example, threads won't be collected as long as they are still running.
Here's a quick test:
class Program
{
static void Main(string[] args)
{
Something something = new Something();
Foo(something);
Console.ReadKey(true);
GC.Collect();
Console.ReadKey(true);
}
private static void Foo(Something something)
{
Timer timer = new Timer(new TimerCallback(something.DoIt),null,0,5);
return;
}
}
public class Something
{
public void DoIt(object state)
{
Console.WriteLine("foo{0}", DateTime.Now.Ticks);
}
}
This is essentially what the compiler blows it out to (the Lambda expression in your example). When you run this, you'll notice that as long as you don't hit the first key, it'll keep putting stuff out to the console. As soon as you hit a key, and the GC kicks in, it stops. Timer still has a reference to Something, but nothing has a reference to Timer, so it's gone.
If you're talking about System.Threading.Timer, it implements IDisposable, so you should maintain a reference to it so that you can call Dispose when you're no longer using it. I don't know the answer to your particular question, but you can investigate it in a console application by running many iterations and forcing GC.Collect() to see if the Timer continues to fire. My guess is that it will eventually be collected and stop firing, unless there is some statically rooted reference created internally.
On a side note, if you want a one-time Fire-and-forget timer, you can implement one by creating a state object with a reference to the Timer, so it can Dispose itself when the timer event fires. I have a TimerService class with a WhenElapsed(TimeSpan, Action) method that uses this pattern and it's very handy for creating timeouts without having to manage the Timer instance as a field in the containing class.
I have the same problem as described in this topic How to let Timer skip tick if the previous thread is still busy
I don't know if I should create new topic for my problem, or I can "up" somehow existent thread (please let me know if i'm wrong creating new topic)
I wrote such solution:
Mutex refreshMutex = new Mutex();
void OnRefreshTimedEvent(object source, ElapsedEventArgs args)
{
try
{
refreshMutex.WaitOne();
// do work
} finally
{
refreshMutex.ReleaseMutex();
}
}
I think it's better because it's thread-safe and doesn't lock entiry object. I would appreciate any comments cause I'm pretty novice in C# :)
Does anyone see any potential problems with what I've shared? I can't ask as an answer on the other discussion.
upd Well it seems solution above doesn't work (thanks to user24601 for noticing). But I don't like the answer from referenced question because the call to serviceTimer.Stop() is not thread-safe. It could be a problem in the extreme frequent timers theoretically (and probably practically), especially if system is used intensively (100% CPU load etc.). I'm thinking now about such pattern:
[MethodImpl(MethodImplOptions.Synchronized)]
void serviceTimer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
serviceTimer.Stop();
// do some heavy processing...
}
finally
{
serviceTimer.Start();
}
}
This does not actually solve the problem. The Elapsed event is raised on a threadpool thread. When there are a lot of active TP threads in your app, the thread that calls your Elapsed event handler may take several seconds to start running. In fact, several of them may be scheduled while this delay takes place. Stopping the timer does not prevent these delayed threads from running. You can still have more than one thread calling your Elapsed event handler concurrently.
Set the timer's AutoReset property to False. Call the timer's Start() method in the finally block of your Elapsed event handler to get it going again. Or use a System.Threading.Timer with a period of 0. That's an all-around better timer, it doesn't swallow exceptions without a diagnostic either, like System.Timers.Timer does.
Perhaps I'm missing something, but why don't you just disable AutoReset on the timer (assuming you're using System.Timers.Timer- you didn't specify)? Put a try/finally around your Elapsed handler impl to ensure that Start() always gets called when it's done. This way, your timer won't start again until the Elapsed handler has completed.
I have an application that start System.Threading.Timer, then this timer every 5 seconds read some information from a linked database and update GUI on main form of application;
Since the System.Threading.Timer create another thread for the Tick event, i need to use Object.Invoke for updating User Interface on the main Form of application with code like this :
this.Invoke((MethodInvoker)delegate()
{
label1.Text = "Example";
});
The app work very well, but sometimes when the user close the main form and then close the application, if the second thread on timer_tick event is updating the user interface on main thread the user get an ObjectDisposedException.
How can i do for stop and close the threading timer before closing the main form and avoiding then Object disposed exception ?
This is a bit of a tricky proposition as you must ensure the following on a given Close event
The timer is stopped. This is fairly straight forward
The control being updated isn't disposed when the delegate is run. Again straight forward.
The code currently running off of a timer tick has completed. This is harder but doable
There are no pending Invoke methods. This is quite a bit harder to accomplish
I've run into this problem before and I've found that preventing this problem is very problematic and involves a lot of messy, hard to maintain code. It's much easier to instead catch the exceptions that can arise from this situation. Typically I do so by wrapping the Invoke method as follows
static void Invoke(ISynchronizedInvoke invoke, MethodInvoker del) {
try {
invoke.Invoke(del,null);
} catch ( ObjectDisposedException ) {
// Ignore. Control is disposed cannot update the UI.
}
}
There is nothing inherently wrong with ignoring this exception if you're comfortable with the consequences. That is if your comfortable with the UI not updating after it's already been disposed. I certainly am :)
The above doesn't take care of issue #2 though and it still needs to be done manually in your delegate. When working with WinForms I often use the following overload to remove that manual check as well.
static void InvokeControlUpdate(Control control, MethodInvoker del) {
MethodInvoker wrapper = () => {
if ( !control.IsDisposed ) {
del();
}
};
try {
control.Invoke(wrapper,null);
} catch ( ObjectDisposedException ) {
// Ignore. Control is disposed cannot update the UI.
}
}
Note
As Hans noted ObjectDisposedException is not the only exception that can be raised from the Invoke method. There are several others, including at least InvalidOperationException that you need to consider handling.
System.Timers.Timer is a horrible class. There is no good way to stop it reliably, there is always a race and you can't avoid it. The problem is that its Elapsed event gets raised from a threadpool thread. You cannot predict when that thread actually starts running. When you call the Stop() method, that thread may well have already been added to the thread pool but didn't get around to running yet. It is subject to both the Windows thread scheduler and the threadpool scheduler.
You can't even reliably solve it by arbitrarily delaying the closing of the window. The threadpool scheduler can delay the running of a thread by up to 125 seconds in the most extreme cases. You'll reduce the likelihood of an exception by delaying the close by a couple of seconds, it won't be zero. Delaying the close for 2 minutes isn't realistic.
Just don't use it. Either use System.Threading.Timer and make it a one-shot timer that you restart in the event handler. Or use a System.Windows.Forms.Timer, it is synchronous.
A WF Timer should be your choice here because you use Control.Invoke(). The delegate target won't start running until your UI thread goes idle. The exact same behavior you'll get from a WF timer.
Create two booleans called 'StopTimer' and 'TimerStopped'. Set the timer's AutoReset property to false. Then format the Elapsed method to the following:
TimerStopped = false;
Invoke((MethodInvoker)delegate {
// Work to do here.
});
if (!StopTimer)
timer.Start();
else
TimerStopped = true;
This way you are preventing a race condition, checking if the timer should continue and reporting when the method has reached its end.
Now format your FormClosing event as follows:
if (!TimerStopped)
{
StopTimer = true;
Thread waiter = new Thread(new ThreadStart(delegate {
while (!TimerStopped) { }
Invoke((MethodInvoker)delegate { Close(); });
}));
waiter.Start();
e.Cancel = true;
}
else
timer.Dispose();
If the timer hasn't stopped yet, a thread is launched to wait until it has done so and then try to close the form again.
I have an object, a Timeline, that encapsulates a thread. Events can be scheduled on the timeline; the thread will wait until it is time to execute any event, execute it, and go back to sleep (for either (a) the time it takes to get to the next event or (b) indefinitely if there are no more events).
The sleeping is handled with a WaitEventHandle, which is triggered when the list of event is altered (because the sleep delay may need to be adjusted) or when the thread should be stopped (so the thread can terminate gracefully).
The destructor calls Stop(), and I've even implemented IDisposable and Dispose() also calls Stop().
Still, when I use this component in a forms application, my application will never shut down properly when I close the form. For some reason, Stop() is never called, so neither my object's destructor triggers, nor is the Dispose() method called, before .NET decides to wait for all threads to finish.
I suppose the solution would be to explicitly call Dispose() myself on the FormClose event, but since this class is going to be in a library, and it is actually a layer deeper (that is, the application developer will never actually see the Timeline class), this seems very ugly and an extra (unnecessary) gotcha for the application developer. The using() clause, which I would normally use when resource release becomes an issue, doesn't apply as this is going to be a long-lived object.
On the one hand, I can understand that .NET will want to wait for all threads to finish before it does its final round of garbage collection, but in this case that produces a very clumsy situation.
How can I make my thread clean up after itself properly without adding requirements to consumers of my library? Put another way, how can I make .NET notify my object when the application is exiting, but before it will wait for all threads to finish?
EDIT: In response to the people saying that it is ok for the client program to be aware of the thread: I respectfully disagree.
As I said in my original post, the thread is hidden away in another object (an Animator). I instantiate an Animator for another object, and I tell it to perform animations, such as "blink this light for 800ms".
As a consumer of the Animator object, I do not care how the Animator makes sure that the light blinks for exactly 800ms. Does it start a thread? I don't care. Does it create a hidden window and use system timers (ew)? I don't care. Does it hire midgets to turn my light on and off? I don't care.
And I especially don't want to have to care that if I ever create an Animator, I have to keep track of it and call a special method when my program exits, in contrast to every other object. It should be a concern of the library implementor, not the library consumer.
EDIT: The code is actually short enough to show. I'll include it for reference, sans methods that add events to the list:
internal class Timeline : IDisposable {
private Thread eventThread;
private volatile bool active;
private SortedList<DateTime, MethodInvoker> events = new SortedList<DateTime,MethodInvoker>();
private EventWaitHandle wakeup = new EventWaitHandle(false, EventResetMode.AutoReset);
internal Timeline() {
active = true;
eventThread = new Thread(executeEvents);
eventThread.Start();
}
~Timeline() {
Dispose();
}
private DateTime NextEvent {
get {
lock(events)
return events.Keys[0];
}
}
private void executeEvents() {
while (active) {
// Process all events that are due
while (events.Count > 0 && NextEvent <= DateTime.Now) {
lock(events) {
events.Values[0]();
events.RemoveAt(0);
}
}
// Wait for the next event, or until one is scheduled
if (events.Count > 0)
wakeup.WaitOne((int)(NextEvent - DateTime.Now).TotalMilliseconds);
else
wakeup.WaitOne();
}
}
internal void Stop() {
active = false;
wakeup.Set();
}
public void Dispose() {
Stop();
}
}
Maybe set the Thread.IsBackground property to true?
eventThread = new Thread(executeEvents);
eventThread.IsBackground = true;
eventThread.Start();
Another option is to use the Interrupt method to wake it up. Just make sure that you catch the ThreadInterruptedException in the thread that you are interrupting, and that it shuts down when it happens.
active = false;
eventThread.Interrupt();
try { eventThread.Join(); } // Wait for graceful shutdown
catch (Exception) { }
Not quite sure how that EventWaitHandle of yours works though... When I did something similar once, I just used the regular Thread.Sleep =)
I don't think it is unreasonable to require clients to Stop() the thread for shutdown at all. There are ways you can create threads whose continued execution will not stop the application from exiting (although I don't have the details off the top of my head). But expecting to launch and terminate a worker thread is not too much of a burden for the client.
There is no way to get .NET to notify your thread without the clients cooperation. If you're designing your library to have a long running background thread, then the client app has to be designed to know about it.
Application::ApplicationExit is a static event, is it acceptable to listen for it and do your special cleanup work?
Implementing IDisposable should be enough indication that your clients should be using your class in a "using" block.
Implement IDisposable properly, including implementing a finaliser that calls Dispose(true). You Animator object can then do any clean up it wishes to, including stopping the thread if necessary.