Pausable Timer on separate thread - c#

I need timer running on separate thread that can be paused and resumed.
The System.Threading.Timer would be ok. but I notice that it spawns new threads even while I'm debugging the callback. I don't want next callback to started before first one is finished, I would like to pause the timer during execution of the callback.
The System.Threading.Timer cannot be paused.
I'm not going to measure any time so no System.Diagnostics.Stopwatch.
In this qestion someone implemented his own class deriving from Timer but I have no idea what timer is this - the System.Threading.Timer is sealed.
System.Windows.Threading.DispatcherTimer can be stopped but the callback is dispatched on UI thread and I'm not sure about portability of this class.
What should I do?

You could instead of using a timer just make it a loop with a delay:
public static async Task RepeatingTask()
{
while(true)
{
Console.WriteLine( "Doing cool stuff" );
await Task.Delay( 2000 );
}
}
And you can start it like this:
Task.Run( RepeatingTask );
NOTE: this will not do the trick if you need to fire every say 2 seconds exactly.

Related

How do run code on the same thread with System.Threading.Timer c#

I have a application which should run a method every few seconds but wait until the previous run is finished. I have solved that by disabling the timer before the metod runs as in the code below. I have some doubts that another thread is invoked from time to time anyway. I would like to run everything on the same thread. Any ideas on how to do that using system.threading.timer?
Thanks in advance.
timer = new System.Threading.Timer((e) =>
{
Console.WriteLine("*** Running Code *** ");
Console.WriteLine(DateTime.Now);
timer.Change(Timeout.Infinite, Timeout.Infinite);
MyMethod();
timer.Change(periodTimeSpanGet,periodTimeSpanGet);
Console.WriteLine("*** Code Finished Code *** ");
Console.WriteLine(DateTime.Now);
}
, null, startTimeSpan, periodTimeSpanGet);
`
Why not just run an async loop?
while(someCondition)
{
DoTheWork();
await Task.Delay(someAmountOfTime);
}
If timing is of importance, you can run a StopWatch to measure the passage of time and do some calculations to figure out what someAmountOfTime should be. Otherwise, just use a constant value.
You'll want to use a shared semaphore to limit concurrent executions of your method to 1 at a time. Instantiate the semaphore once before starting the timer, and reuse it in every execution of the timer.
When the method starts, you'll want to wait for the semaphore to become available. At the end of the method, you'll want to release the semaphore. This ensures only one execution occurs at a time between the wait and the release.
Using a semaphore is better than a lock because it allows you to supply a timeout, a maximum amount of time to wait before giving up.
https://learn.microsoft.com/dotnet/standard/threading/semaphore-and-semaphoreslim

How to create an application loop in C#

I have a console server in C# that keeps running in a while(true) loop. But that takes > 50% CPU even if it is doing nothing. I tried Thread.Sleep it worked! Not eating my CPU anymore but, it do not resumes in the exact time specified and is not considered good practice. Am I doing the right thing? Or is there any other way than using while(true) and Thread.Sleep?
When you want to suspend thread for a while without consuming CPU resources, you usually use some WaitHandle (such as AutoResetEvent or ManualResetEvent) and call it's WaitOne() method to suspend thread until event that is supposed to wake it up occurs (e.g. key is pressed, new network connection arrives, asynchronous operation finishes, etc.).
To wake up thread periodically, you can use timer. I'm not aware of any timer in .NET Framework, that provides WaitHandle (of course you can easily create such class yourself), so have to use Timer and call AutoResetEvent.Set() manually on each tick in it's callback.
private static AutoResetEvent TimerWaitHandle = new AutoResetEvent(false);
static void Main()
{
// Initialize timer
var timerPeriod = TimeSpan.FromMilliseconds(500);
Timer timer = new Timer(TimerCallback, null, timerPeriod, timerPeriod);
while(true)
{
// Here perform your game logic
// Suspend main thread until next timer's tick
TimerWaitHandle.WaitOne();
// It is sometimes useful to wake up thread by more than event,
// for example when new user connects etc. WaitHandle.WaitAny()
// allows you to wake up thread by any event, whichever occurs first.
//WaitHandle.WaitAny(new[] { TimerWaitHandle, tcpListener.BeginAcceptSocket(...).AsyncWaitHandle });
}
}
static void TimerCallback(Object state)
{
// If possible, you can perform desired game logic here, but if you
// need to handle it on main thread, wake it using TimerWaitHandle.Set()
TimerWaitHandle.Set();
}
I can't comment, so i'll put it here.
Theorically with Thread.sleep(1) it won't use that much CPU.
You can get more info from this question/answer: What is the impact of Thread.Sleep(1) in C#?
You can use System.Threading.Timer class. It Provides a mechanism for executing a method on a thread pool thread at specified intervals.
Example
public void Start()
{
}
int dueTime = 1000;
int periodTS = 5000;
System.Threading.Timer myTimer = new System.Threading.Timer(new TimerCallback(Start), null, dueTime, periodTS);
This will call start method after 1 second from calling it and after that start will be called after every 5 second.
You can read more about Timer class here.

Scheduling Task for future execution

I have looked at the Task and Timer class API's, but could not find information on how to schedule a Task for future execution.
Using the Timer class, I can schedule threads for future execution, but I need to schedule Tasks.
Task has .Delay(...) methods, but not sure delay is similar to scheduling.
Edit(clarification): I want to start tasks after x minutes.
You should use Task.Delay (which internally is implemented using a System.Threading.Timer):
async Task Foo()
{
await Task.Delay(TimeSpan.FromMinutes(30));
// Do something
}
While the delay is "executed" there is no thread being used. When the wait ends the work after it would be scheduled for execution.
I would use this Timer (System.Timers.Timer) instead. It's a bit simpler to use. Set the interval to 30 and start the timer, making sure the elapsed event calls the method you want to happen. You can stop it afterwards if you only want it to happen once and not every thirty minutes.
Code sample from the linked MSDN page:
// Create a timer with a two second interval.
aTimer = new System.Timers.Timer(2000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += OnTimedEvent;
aTimer.Enabled = true;
//schedule stuff to run after 2 seconds
Task.Delay(2000).ContinueWith(t => {
//do something
});

C# ThreadPool and ElapsedEventHandler

I have an application which should finish within 30 minutes. The components of the application are run using threadpool.
So
//queue first all the components
//when the Collect method for each of the components finishes it will set the event
ManualResetEvent serverEvent = new ManualResetEvent(false);
sectionsCompleted.Add(serverEvent);
ThreadPool.QueueUserWorkItem(serverInfo.Collect,"ServerInfo ");
ManualResetEvent cpuEvent= new ManualResetEvent(false);
sectionsCompleted.Add(cpuEvent);
ThreadPool.QueueUserWorkItem(cpuInfo.Collect,"CPUInfo ");
//then wait for all the components to finish
WaitHandle.WaitAll(sectionsCompleted.ToArray());
So the logic is to call all the components in ThreadPool and use ManualResetEvent class to signal the main thread that the component has finished.
Now i want to use the ElapsedEvent Handler to make sure that the code finishes gracefully in some time frame(say 30 minutes). So after 30 minutes if there are still some threads running i want to abort them.
So my question will ElapsedEventHandler delegate be called at all? or will the main thread wait for WaitHandle.WaitAll(sectionsCompleted.ToArray()) ?
Is there any other way i can achieve this functionality of stopping all threads in a thread pool after some time interval.
If you setup the timer, the event handler for the timer, and start the timer before the above code (or at least before the WaitAll) then
your timer's Elapsed event will fire,
your Main thread will wait at the WaitAll
but you could just as easily do something like:
if (!WaitHandle.WaitAll(sectionsCompleted.ToArray(), TimeSpan.FromMinutes(30)))
{
// did not finish in the 30 minute timespan, so kill the threads
}
If you do the above you won't have to worry about synchronising your event handler for the timer (which may try and kill a thread just as it completes) and the Main method which is waiting on the WaitHandles (and may therefore complete while the event handler thinks the thread is being killed).
If you are able (.NET version depending) then Tasks would be very well suited to this as you could use a CancellationToken to allow you to kill each task gracefully if it has not completed. See MSDN: Task Cancellation for something like the below. If you can't use Task you can just wire this same solution up yourself. One possible technique is to use more WaitHandles (also see below).
This approach will also let you move the Wait+Cancel code into a separate thread. You can therefore release your UI or main code thread immediately the worker threads are created. This has the added advantage that you can also signal from the control thread to the single instance of the Wait+Cancel code to trigger a premature cancellation.
// use the same CancellationTokenSource to create all tasks
var tokenSource2 = new CancellationTokenSource();
// for each task, use the following structure
CancellationToken ct = tokenSource2.Token;
var task = Task.Factory.StartNew(() =>
{
// Were we already canceled?
ct.ThrowIfCancellationRequested();
bool moreToDo = true;
// make sure any loops and other methods check the ct.IsCancellationRequested regularly
while (moreToDo)
{
if (ct.IsCancellationRequested)
{
// Clean up any resources, transactions etc. here, then...
ct.ThrowIfCancellationRequested();
}
}
}, tokenSource2.Token); // Pass same token to StartNew.
// add each task to the tasks list
tasks.Add(task);
// once all tasks created, wait on them and cancel if they overrun
// by passing the token, another thread could even cancel the whole operation ahead of time
if (!Task.WaitAll(tasks.ToArray(), (int)TimeSpan.FromMinutes(30).TotalMilliseconds,
tokenSource2.Token))
{
// did not finish in the 30 minute timespan, so kill the threads
tokenSource2.Cancel();
try
{
// Now wait for the tasks to cancel
Task.WaitAll(tasks.ToArray());
}
catch (AggregateException ae)
{
// handle any unexpected task exceptions here
}
}
Or in .NET 2.0 without Tasks:
// in Main thread ...
ManualResetEvent serverEventCancelled = new ManualResetEvent(false);
cancellationMres.Add(serverEventCancelled);
// Inside the thread, do this regularly - zero timeout returns instantly ...
if (serverEventCancelled.WaitOne(0))
{
// do cancellation and ...
// now set the "completed" waithandle (or do something similar to let Main know we are done)
serverEvent.Set();
return;
}
// In Main thread ...
if (!WaitHandle.WaitAll(sectionsCompleted.ToArray(), TimeSpan.FromMinutes(30)))
{
foreach (var cancellationMre in cancellationMres)
{
cancellationMre.Set();
}
WaitHandle.WaitAll(sectionsCompleted.ToArray());
}
ElapsedEventHandler delegate be called at all?
yes
will the main thread wait for WaitHandle.WaitAll(sectionsCompleted.ToArray()) ?
yes
but you need to signal the eventhandler in your thread(like cpuInfo.Collect) ,
in .net 4.5, you also can use CancellationTokenSource(TimeSpan) to cancel the thread after period time.
btw: you should put WaitHandle.WaitAll(sectionsCompleted.ToArray()) in non-ui thread, or it will block your UI.

Scheduled operations in C# with option to FullStop immediately

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.

Categories