C# keep event handling thread alive in CPU friendly way - c#

I would like to run 10 threads in parallel. Each thread contains code that handles serial port communication (Using the 'SerialPort' class). Some of the features are:
Code for handling the event that is raised when the RS232 device returns data.
Code for handling Timer events that are raised when the RS232 device does not return data within a predefined time frame.
As you can see each thread handles some asynchronous events initialized and started from the thread itself. So the thread needs to keep itself alive until all events have been raised and processed. Based on the received data from the RS232 device the thread knows when the work is done and the thread can kill itself.
Now my question: I would like to avoid using an infinite loop to keep the thread alive to avoid using a lot of CPU resources on nothing. Any idea how to do this and also avoiding that the thread blocks/stops itself?.

The most efficient way to keep the 10 threads idle based on a condition is to use a WaitHandle.
The ManualResetEvent class allows you to simply signal when you want to continue execution. You can signal multiple threads with the same handle.
class Work
{
public static void WorkMethod(object stateInfo)
{
Console.WriteLine("Work starting.");
((ManualResetEvent)stateInfo).WaitOne();
Console.WriteLine("Work ending.");
}
}
// Example:
ManualResetEvent manualEvent = new ManualResetEvent(false);
Thread newThread = new Thread(Work.WorkMethod);
newThread.Start(manualEvent);
// This will terminate all threads that are waiting on this handle:
manualEvent.Set();

Related

killing a long running thread that is blocking on another child process to end

So, a little background. I have a program that creates a child process that runs long term and does some processing that we don't really care about for this question. It exists, and it needs to keep existing. So after starting that child process I start a thread that watches that child process and blocks waiting for it to end by Process.WaitForExit() and if it ends, it will restart the child process and then wait again. Now the problem is, how do I gracefully shut all of this down? If I kill the child process first, the thread waiting on it will spin it up again, so I know that the watcher thread needs to be killed first. I have been doing this by Thread.Abort() and then just catching the ThreadAbortException and returning ending the watcher thread and then I kill my child process. But I have been told that Thread.Abort() should be avoided at all costs and is possibly no longer supported in .Net core? So my question is why is Thread.Abort() so dangerous if I am catching the ThreadAbortException? and what is the best practice for immediately killing that thread so it doesn't have a chance to spin up the child thread again during shut down?
What you are looking for is way to communicate across threads. There are multiple ways to do this but they all have specific conditions applicable.
For example mutex and semaphore are available across processes. events or wait handles are specific to a given process, etc. Once you know the details of these you can use them to send signal from one thread to another.
A simple setup for your requirement can be -
Create a resetevent before spawning any of your threads.
Let the child thread begin. In your parent wait on the reset event that you have created.
Let the child thread reset the event.
In your parent thread the wait state is completed, you can take further actions, such as kicking of the thread again and waiting on it or simply cleaning up and walking out of execution.
Thread.Abort is an unclean way of finishing your processing. If you read the msdn article here - https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread.abort?view=net-6.0 the remark clearly tells you that you cant be sure what current state your thread execution was in. Your thread may not get opportunity to follow up with important clean up tasks, such as releasing resources that it does not require no more.
This can also lead to deadlock if you have more complicated constructs in place, such as thread being aborted doing so from protected region of code, such as a catch block or a finally block. If the thread that calls Abort holds a lock that the aborted thread is waiting on, a deadlock can acquire.
Key to remember in multithreading is that it is your responsibility to let the logic have a clean way of reaching to completion and finish thread's execution.
Please note that steps suggested above is one way of doing it. Depending on your requirements it can be restructured/imporved further. For example, if you are spawning another process, you will require kernel level objects such as mutex or semaphore. Objects like event or flag cant work across the process.
Read here - https://learn.microsoft.com/en-us/dotnet/standard/threading/overview-of-synchronization-primitives for more information.
As mentioned by others, Thread.Abort has major issues, and should be avoided if at all possible. It can raise the exception at any point in the code, in a possibly completely unexpected location, and possibly leave data in a highly corrupted state.
In this instance, it's entirely unnecessary.
You should change the waiting thread to use async instead. For example, you can do something like this.
static async Task RunProcessWithRestart()
{
using cancel = new CancellationTokenSource();
try
{
while (true)
{
using (var process = CreateMyProcessAndStart())
{
await process.WaitForExitAsync(cancel.Token);
}
}
}
catch(OperationCanceledException)
{
}
}
static CancellationTokenSource cancel;
public static void StartWaitForProcess()
{
Task.Run(RunProcessWithRestart);
}
public static void ShutdownWaitForProcess()
{
cancel.Cancel();
}
An alternative, which doesn't require calling Cancel() from a separate shutdown function, is to subscribe to the AppDomain.ProcessExit event.
static async Task RunProcessWithRestart()
{
using var cancel = new CancellationTokenSource();
AppDomain.ProcessExit += (s, e) => cancel.Cancel();
try
{
while (true)
{
using (var process = CreateMyProcessAndStart())
{
await process.WaitForExitAsync(cancel.Token);
}
}
}
catch(OperationCanceledException)
{
}
}
public static void StartWaitForProcess()
{
Task.Run(RunProcessWithRestart);
}

Thread persists after application termination due to AutoResetEvent signal in WaitOne state

I have an application that uses an AutoResetEvent (WaitOne/Set) in a queue for processing messages. I'm noticing that when I terminate the a debug session from Visual Studio (Shift+F5) the original process for the application hangs around (but not always). I manually re-attach the debugger to the process, and see it has single thread stuck on WaitHandle.WaitOne.
So my question is, what is the correct way to terminate threads that may be in a WaitOne state?
The first answer that sprang to mind was listen to the Application Exit event and doing a Set there, but I wasn't sure if this event was called reliably after these debug sessions, or if there is a more standard practice that I am not aware of.
And, as a second question, would you handle this differently for the application running in 'production' mode?
There is a simple way to do this (not a workaround)
First, you need to set an event that will fire when your application is going to die
// somewhere with global scope. On a singleton or in program class maybe
// this is set when you want to terminate your application
private static ManualResetEvent ExitWaitHandle = new ManualResetEvent(false);
And this is how to use it elsewhere
// the event you want to check but it's blocking your application termination
private static AutoResetEvent yourEvent = new AutoResetEvent(true);
// the method where you have the problem
private static void FooAsync()
{
try
{
WaitHandle.WaitAny(new WaitHandle[]{yourEvent, ExitWaitHandle});
Checkpoint();
// other stuff here
// check if thread must die
Checkpoint();
}
catch(ApplicationTerminatingException)
{
// thread must die, do cleanup and finalization stuff here
}
catch(Exception)
{
// holy cow! what should we do?
}
}
private void CheckPoint()
{
// fast check if the exit handle is set
if(ExitWaitHandle.WaitOne(0))
{
throw new ApplicationTerminatingException(); // custom exception
}
}
The only overhead is that after "some" code you need to set a checkpoint in order to abort your thread. Hope this is what you were looking for.
One solution is to set the thread as background thread using the Thread.IsBackground property. When set on a thread that thread will not stop a process for exiting.
However, the thread may be interrupted at any time usually leading to undefined behavior depending on what your thread is doing. The best way to terminate a thread in my humble opinion is to signal the thread to exit, e.g. by setting a quit flag and set the WaitHandle and to wake it up then Joining the thread.

How can I ensure a determenistic result for this multithreading problem?

Consider the following test snippet:
// act
AutoResetEvent workDoneEvent = new AutoResetEvent(false);
ThreadPool.QueueUserWorkItem(delegate
{
ProcessAndSignal(processor, workDoneEvent);
}, null);
// let worker thread have a go
workDoneEvent.WaitOne();
blockingFetcher.WaitForNextMessage = false;
// assert
Assert.That(processor.StopCause, Is.Null);
}
private static void ProcessAndSignal(MessageProcessor processor, AutoResetEvent workDoneEvent)
{
workDoneEvent.Set();
// this invocation will block until the WaitForNextMessageFlag is set
processor.ProcessMessages();
}
Ideal scenario:
ProcessAndSignalMethod is queued on the thread pool but does not start to execute.
The main thread blocks (autoResetEvent.WaitOne())
A worker thread starts to execute the "ProcessAndSignal" method
The worker threads has enough time to signal the flag and start execution of the ProcessMessages method
The main thread is spawned back into life and sets the property which will cause the ProcessAndSignal method to complete gracefully
Can the following scenario occur?
1) ProcessAndSignal() will start to execute before the main thread sets the AutoResetEvent to WaitOne() which will cause a deadlock (the processor.ProcessMessages() will go into an infinitive loop)
Yes, the scenario can occur. Yes it can deadlock if you don't declare the bool variable as volatile. Just don't use a bool, use an event like you did.
The logic looks weird, it smells like you are trying to let the main thread wait for the processing to be completed. The workDoneEvent doesn't actually signal that the work was done. Right now the main thread will check the assert before the worker is done, that can't be good. If the intention was that it signals that the worker is done then ProcessAndSignal should be the one calling Set(), at the end of the method. And the main thread should call WaitOne().
If this is at all accurate then you just should not use QUWI, just call ProcessAndSignal directly without using a thread. Far more efficient, zero odds for threading problems.

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.

.NET Thread Synchronization

I am planning to use Auto reset Event Handle for Inter Thread communication.
EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.AutoReset);
My producer thread code look like below
produceSomething();
handle.Set();
In the consumer thread, I have to download data for every one minute or when producer
is called Set method
try
{
while(true)
{
handle.WaitOne(60000, false);
doSomething(); // Downloads data from Internet.
// Takes lot of time to complete it.
}
}
catch(ThreadAbortException)
{
cleanup();
}
My question is if consumer thread is running doSomething function and producer calls set function, what would be state of Auto reset event object?
My requirement is as soon as producer calls set method I have to download fresh data from the Internet. If doSomething function is running, when Producer calls set method, I have to interrupt it and call again.
An auto-reset event is like a gate that closes after the first thread goes through. If you set it while one or more threads are waiting then One thread wakes up, then the event is reset, the rest of the threads continue to wait.
If you set when no threads are waiting, then the first thread that calls handle.WaitOne will not wait, but it will cause the event to get reset and then continue on.
from http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx
Calling Set signals AutoResetEvent to release a waiting thread. AutoResetEvent remains signaled until a single waiting thread is released, and then automatically returns to the non-signaled state. If no threads are waiting, the state remains signaled indefinitely.
If a thread calls WaitOne while the AutoResetEvent is in the signaled state, the thread does not block. The AutoResetEvent releases the thread immediately and returns to the non-signaled state.
The problem with auto-reset event in your scenario is that "setting" it do not supports queuing.
That is, setting an auto-reset event allows one thread to enter, if you set it again before any thread "consumes" your event, then that "set" will be lost. You might expect for two threads to be able to enter and consume whatever you have produced but in fact only ONE thread will be able to do that.
In your case, if you're producing at a faster rate than you're consuming then the auto-reset event might be missleading. Imagine this case.
The producer produces one item.
The consumer consumes the item (resets the event and starts downloading from inet)
The producer produces a second item.
The producer produces a third item.
The produce stops.
The consumer consumes the second item (resests the event and starts downloading again)
The consumer WON'T cosume the third item ever because the autoreset event has been reset.

Categories