Reliably stop System.Threading.Timer?
like Conrad Frix suggested you should use the System.Timers.Timer
class instead, like:
private System.Timers.Timer _timer = new System.Timers.Timer();
private volatile bool _requestStop = false;
public constructor()
{
_timer.Interval = 100;
_timer.Elapsed += OnTimerElapsed;
_timer.AutoReset = false;
_timer.Start();
}
private void OnTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
{
// do work....
if (!_requestStop)
{
_timer.Start();//restart the timer
}
}
private void Stop()
{
_requestStop = true;
_timer.Stop();
}
private void Start()
{
_requestStop = false;
_timer.Start();
}
Best way to disable a System.Threading.Timer
Setting a timer's initial value and interval to -1 (i.e. Change(-1, -1)
) is not a "CPU heater." Timers don't use CPU resources. The callback method does, of course, but only during the (usually brief) time when it's executing.
In any case, it is not at all expensive to create a new timer, nor will disabling it with Change(-1, -1)
have any negative performance consequences. Use whichever technique best fits your model.
How to STOP a System.Threading.Timer
I need to know how I can stop a System.Threading.Timer because when they order a taxi, cancel it after lets say 8 seconds then straight after they order another taxi, that taxi takes 2 seconds to come not 10 so it still uses the old taxi timer, how do I stop it?
Take a step back. You don't have to worry about canceling a timer if you never make one.
You are describing an asynchronous workflow with cancellation. C# and the .NET framework already has this feature, so use it rather than trying to roll your own.
Make an async
workflow method that await
s a Task.Delay
task that takes a CancellationToken
. The continuation of the delay is the arrival of the taxi; the cancellation method causes the task to fail by canceling the token.
There is plenty of documentation on this mechanism, so start reading it. A good place to start is here:
https://msdn.microsoft.com/en-us/library/dd997364
How to stop a System.Threading.Timer and cancel any callback that is running?
According to the documentation, you should use the Dispose(WaitHandle)
overload:
Releases all resources used by the current instance of Timer and signals when the timer has been disposed of.
When this method completes, it signals the
WaitHandle
specified by thenotifyObject
parameter.Use this overload of theDispose
method if you want to be able to block until you are certain that the timer has been disposed. The timer is not disposed until all currently queued callbacks have completed.
void Dispose()
{
timer.Change(Timeout.Infinite, Timeout.Infinite); //Stop timer
var waiter = new ManualResetEvent(false);
timer.Dispose(waiter);
waiter.WaitOne();
waiter.Dispose();
timerSync.Dispose();
//Dispose other things...
}
If you don't want to wait for the current callback to be executed at all, you could follow the IDisposable
pattern:
Timer timer = new Timer(Timer_Tick, null, Timeout.Infinite, Timeout.Infinite);
Mutex timerSync = new Mutex();
private bool _disposed;
void Dispose()
{
_disposed = true;
...
}
void Timer_Tick()
{
if (_disposed)
{
return;
}
...
}
Is it possible to stop a threading.Timer immediately?
This is a "feature" of the Timer
. The callback may run on a different thread and it does not even need to terminate before it is called again (for example if its execution takes more that 1000 ms). If you don't need this feature and it is OK to run the callback 1000 ms after the termination of the previous callback you can just avoid passing the period
parameter and restart the timer manually at the end of the callback.
How do I gracefully stop a System.Threading.Timer?
With this code
timer = new Timer( state => {
// simulate some work that takes ten seconds
Thread.Sleep( tickInterval * 10 );
// when the work is done, schedule the next callback in one second
timer.Change( tickInterval, Timeout.Infinite );
},
null,
tickInterval, // first callback in one second
Timeout.Infinite );
it is almost certain that you will Dispose the timer while it is sleeping.
You will have to safeguard the code after Sleep() to detect a Disposed timer. Since there is no IsDisposed property a quick and dirty static bool stopping = false;
might do the trick.
Can I stop a System.Threading.Timer
There is no way to know the Thread
on which a Threading.Timer
callback will run ahead of time. Hence there is no general way to abort it. It is possible to have the callback itself communicate the Thread
instance but it opens up a couple of race conditions
Note: In general using Abort
is a bad practice. It's a fairly reliable way to end up with hard to detect deadlocks and / or resource leaks. It's much better to use a passive mechanism like CancellationToken
How to stop a System.Threading.Timer, then change its parameters and run it again?
I wouldn't re-invent the wheel. Microsoft already has a library that does this nicely for you. You should use Microsoft's Reactive Framework (aka Rx) - NuGet System.Reactive
and add using System.Reactive.Linq;
.
You can do this kind of thing:
IDisposable subscription =
Observable
.Interval(TimeSpan.FromSeconds(1.0))
.Subscribe(x => Console.WriteLine(x));
This will fire an event every second. If you want to stop it just call subscription.Dispose();
If you want a different period then pass in something like TimeSpan.FromDays(2.0)
.
Now, if you want to be able to change the period you can do this:
Subject<TimeSpan> subject = new Subject<TimeSpan>();
IObservable<long> interval =
subject
.Select(timespan => Observable.Interval(timespan))
.Switch();
IDisposable subscription =
interval
.Subscribe(x => Console.WriteLine(x));
Now, to start the interval going I would call this:
subject.OnNext(TimeSpan.FromSeconds(1.0));
If I now want to change it I just do this:
subject.OnNext(TimeSpan.FromHours(2.0));
And, again, to stop it just call subscription.Dispose();
.
Related Topics
Avoiding First Chance Exception Messages When the Exception Is Safely Handled
How to Get the Assembly File Version
How to Show Progress Bar for Upload with Ftpwebrequest
How to Fix "Referenced Assembly Does Not Have a Strong Name" Error
How to Create Custom Config Section in App.Config
Bind to Selecteditems from Datagrid or Listbox in Mvvm
Why Cannot C# Generics Derive from One of the Generic Type Parameters Like They Can in C++ Templates
How to Use a Reserved Keyword as an Identifier in My JSON Model Class
Converting Bitmap Pixelformats in C#
Why Should I Use Ihttpactionresult Instead of Httpresponsemessage
Dynamically Access Table in Ef Core 2.0
Thread.Sleep for Less Than 1 Millisecond
How to Enable Nuget Package Restore in Visual Studio
Understanding Async/Await in C#
What Is the Use of Enumerable.Zip Extension Method in Linq
Using C# .Net Libraries to Check for Imap Messages from Gmail Servers