C# ThreadPool and ElapsedEventHandler - c#

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.

Related

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.

Synchronisation between System.Threading timer tick and background thread

I need to develop following scenario. I have System.Threating.Timer. On each timer tick, some values are retrieved from hardware device, this way:
lock (_synch)
{
//Read some values
}
Also I have many methods invoked in background thread, they also wants to read/write on COM to talk with device, for example:
bool WriteSometghing ()
{
lock(_synch)
{
//Write to device
}
}
It works fine. All of this is synchronised as should, there are no simultaneous access to device from threads. However, I need to my WriteSomething method to be called asynchronously to prevent blocking other operations in my background thread. So WriteSomething should start third thread, do all needed operations and destroy third thread. Of course, still I need to be sure, that there are no simultaneous access to hardware. So it should be synchronised with method called on timer tick. Also I need to synchronise WriteSomething calls (every call is fired on UDP packet receive), so WriteSomething can be invoked simultaneously but all operations inside should be syncrhonised between WriteSomething calls.
Method WriteSomething has to be called from background thread and also third thread should be created from my background thread, in place of current WriteSomething call. Can I simply create third thread as I described, put WriteSomething there and leave my lock as is? Will it be synchronised as should between my 3 threads (first - timer tick, second - background thread, third - background thread for WriteSomething).
Can you give me some tips, how it should be done?
You can simply create a Task to call WriteSomething.
var task = Task.Factory.CreateNew(WriteSomething);
That will spin up a new thread to execute the WriteSomething method. The lock inside the WriteSomething method will provide the necessary synchronization. If you want to harvest the return value, simply access task.Result.
Do note that accessing task.Result requires that the task complete. So if you write:
var task = Task.Factory.CreateNew(WriteSomething);
var rslt = task.Result;
The thread will block until the task is finished. Of course, you can do any arbitrary processing between when you start the task and when you harvest the result.
Edit
If you can't use Task, there are other ways to do this. For example:
bool result;
Thread t = new Thread((s) => { result = WriteSomething(); });
// at some point you'll want to harvest the result:
t.Join();
// Now you can access result

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.

Is there a way to wake a sleeping thread?

Is there a way to wake a sleeping thread in C#? So, have it sleep for either a long time and wake it when you want work processed?
An AutoResetEvent object (or another WaitHandle implementation) can be used to sleep until a signal from another thread is received:
// launch a calculation thread
var waitHandle = new AutoResetEvent(false);
int result;
var calculationThread = new Thread(
delegate
{
// this code will run on the calculation thread
result = FactorSomeLargeNumber();
waitHandle.Set();
});
calculationThread.Start();
// now that the other thread is launched, we can do something else.
DoOtherStuff();
// we've run out of other stuff to do, so sleep until calculation thread finishes
waitHandle.WaitOne();
If your thread is inside a call to Sleep, then there isn't (usually) a way to wake it up. (The only exception I'm aware of is Java, which allows a sleep to be ended early if some other thread calls thread.interrupt().)
The pattern that you're talking about seems to call for an event: the thread contains a loop, at the top of which it waits for an event to fire. If the event is currently unset, then the thread "sleeps" until some other thread fires the event. At that point, the sleeping thread wakes up and continues its work, until the next time through the loop when it sleeps to wait for another event.
There is actually a thread.Interrupt() method in C#.
While the accepted answer does describes a good pattern that you probably want in your case, I came to this question looking for Thread.Interrupt so I am putting it here.
The best solution would be to use Task objects with the default TaskFactory. This API (introduced in .NET 4.0) uses a pool of threads with work-stealing queues and all that fancy stuff.
If .NET 4.0 isn't available, then use the ThreadPool, which has a built-in work queue (which does some pool balancing but not on the same scope as the 4.0 thread pool).
If you really must do it yourself, then I recommend a BlockingCollection<T>, which is a blocking consumer/producer queue added in .NET 4.0.
If you really must do it yourself and can't use .NET 4.0, then you can use a ManualResetEvent or AutoResetEvent along with a lock-protected queue of work.
Expanding Wim's answer you can also specify a timeout for the WaitHandle.WaitOne() call. So you can use instead of Thread.Sleep(). CancellationToken struct provides you with one so you can signal your tasks like this:
string SleepAndWakeUp(string value,CancellationToken ct)
{
ct.WaitHandle.WaitOne(60000);
return value;
}
void Parent()
{
CancellationTokenSource cts = new CancellationTokenSource();
Task.Run(() => SleepAndWakeUp("Hello World!", cts.Token), cts.Token);
//Do some other work here
cts.Cancel(); //Wake up the asynch task
}
Would this thread help? C# has good functionality for thread Event handling. I've done most of my work in Python, but C# seems to have solid libraries for thread blocking.
Based on Ilia's suggestion:
t1 = new Thread(() =>
{
while (keepRunning) {
try {
DoWork();
Thread.Sleep(all_night_long);
}
catch (ThreadInterruptedException) { }
}
});
t1.Start();
and...
public void WakeUp()
{
t1.Interrupt();
}
public void StopRunningImmediately()
{
keepRunning = false;
WakeUp(); //immediately
}
This solution is crude, as there may be other reasons why the ThreadInterruptedException is thrown.

How do I block until a thread is returned to the pool?

As part of a windows service
I'm accepting incoming socket connection using
myListener.BeginAcceptSocket(acceptAsync, null)
The acceptAsync function executes on a seperate thread (just as expected).
When the service is requested to shutdown, I "signal" the threads that accepted and are currently working on the sockets, to finish up.
After signaling each thread to end,I need to block until they are all done. I have a list of threads, that I thought I could iterate through and Join each thread until they were all done.
Howerver it seems that these threads don't end, but return to the pool, so the Join will wait for ever.
How do I block until a thread is returned to the pool?
You shouldn't use Join in this case. Rather, you should use a series of WaitHandles (specifically, an AutoResetEvent or ManualResetEvent) which your threads will signal when they are done with their work.
You would then call the static WaitAll method on the WaitHandle class, passing all of the events to wait on.
The canonical pattern for doing this is to use a CountdownEvent. The main thread will increment the event to indicate that it is participating and the worker threads will do the same once they start. After the worker threads have finished they will decrement the event. When the main thread is ready to wait for completion it should decrement the event and then wait on it. If you are not using .NET 4.0 then you can get an implemention of a countdown event from part 4 of Joe Albahari's threading ebook.
public class Example
{
private CountdownEvent m_Finisher = new CountdownEvent(0);
public void MainThread()
{
m_Finisher.AddCount();
// Your stuff goes here.
// myListener.BeginAcceptSocket(OnAcceptSocket, null);
m_Finisher.Signal();
m_Finisher.Wait();
}
private void OnAcceptSocket(object state)
{
m_Finisher.AddCount()
try
{
// Your stuff goes here.
}
finally
{
m_Finisher.Signal();
}
}
}
The best way would be to change acceptAsync so that it signals on a semaphore, your main thread can then wait on that semaphore.
You don't have a lot of acces to or control over Threapool threads.

Categories