What is the reason for "while(true) { Thread.Sleep }"? - c#

I sometimes encounter code in the following form:
while (true) {
//do something
Thread.Sleep(1000);
}
I was wondering if this is considered good or bad practice and if there are any alternatives.
Usually I "find" such code in the main-function of services.
I recently saw code in the "Run" function in a windows azure worker role which had the following form:
ClassXYZ xyz = new ClassXYZ(); //ClassXYZ creates separate Threads which execute code
while (true) {
Thread.Sleep(1000);
}
I assume there are better ways to prevent a service (or azure worker role) from exiting.
Does anyone have a suggestion for me?

Well when you do that with Thread.Sleep(1000), your processor wastes a tiny amount of time to wake up and do nothing.
You could do something similar with CancelationTokenSource.
When you call WaitOne(), it will wait until it receives a signal.
CancellationTokenSource cancelSource = new CancellationTokenSource();
public override void Run()
{
//do stuff
cancelSource.Token.WaitHandle.WaitOne();
}
public override void OnStop()
{
cancelSource.Cancel();
}
This will keep the Run() method from exiting without wasting your CPU time on busy waiting.

An alternative approach may be using an AutoResetEvent and instantiate it signaled by default.
public class Program
{
public static readonly AutoResetEvent ResetEvent = new AutoResetEvent(true);
public static void Main(string[] args)
{
Task.Factory.StartNew
(
() =>
{
// Imagine sleep is a long task which ends in 10 seconds
Thread.Sleep(10000);
// We release the whole AutoResetEvent
ResetEvent.Set();
}
);
// Once other thread sets the AutoResetEvent, the program ends
ResetEvent.WaitOne();
}
}
Is the so-called while(true) a bad practice?
Well, in fact, a literal true as while loop condition may be considered a bad practice, since it's an unbrekeable loop: I would always use a variable condition which may result in true or false.
When I would use a while loop or something like the AutoResetEvent approach?
When to use while loop...
...when you need to execute code while waiting the program to end.
When to use AutoResetEvent approach...
...when you just need to hold the main thread in order to prevent the program to end, but such main thread just needs to wait until some other thread requests a program exit.

If you see code like this...
while (true)
{
//do something
Thread.Sleep(1000);
}
It's most likely using Sleep() as a means of waiting for some event to occur — something like user input/interaction, a change in the file system (such as a file being created or modified in a folder, network or device event, etc. That would suggest using more appropriate tools:
If the code is waiting for a change in the file system, use a FileSystemWatcher.
If the code is waiting for a thread or process to complete, or a network event to occur, use the appropriate synchronization primitive and WaitOne(), WaitAny() or WaitAll() as appropriate. If you use an overload with a timeout in a loop, it gives you cancelability as well.
But without knowing the actual context, it's rather hard to say categorically that it's either good, bad or indifferent. If you've got a daemon running that has to poll on a regular basis (say an NTP client), a loop like that would make perfect sense (though the daemon would need some logic to monitor for shutdown events occuring.) And even with something like that, you could replace it with a scheduled task: a different, but not necessarily better, design.

If you use while(true) you have no programmatic means of ending the loop from outside the loop.
I'd prefer, at least, a while(mySingletonValue) which would allow us to switch the loop as needed.
An additional approach would be to remove the functional behavior from the looping behavior. Your loop my still be infinite but it calls a function defined elsewhere. Therefore the looping behavior is completely isolated to what is being executed by the loop:
while(GetMySingletonValue())
{
someFunction();
}
In this way your singleton controls the looping behavior entirely.

There are better ways to keep the Azure Service and exit when needed.
Refer:
http://magnusmartensson.com/howto-wait-in-a-workerrole-using-system-timers-timer-and-system-threading-eventwaithandle-over-system-threading-thread-sleep
http://blogs.lessthandot.com/index.php/DesktopDev/MSTech/azure-worker-role-exiting-safely/

It really depends on that //do something on how it determines when to break out of the loop.
In general terms, more appropriate way to do it is to use some synchronization primitive (like ManualResetEvent) to wait on, and the code that processes and triggers the break of the loop (on the other thread) to signal on that primitive. This way you don't have thread wasting resources by being scheduled in every second to do nothing, and is a much cleaner way to do it.

I personally don't like Thread.Sleep code. Because it locks the main thread. You can write something like this, if it is a windows application besides it allows you more flexibility and you can call it async:
bool switchControl = true;
while (switchControl) {
//do something
await Wait(1);
}
async void Wait(int Seconds)
{
DateTime Tthen = DateTime.Now;
do
{
Application.DoEvents(); //Or something else or leave empty;
} while (Tthen.AddSeconds(Seconds) > DateTime.Now);
}

Related

Does SemaphoreSlim's timeout defeat its own purpose?

The true power of semaphore is :
Limits the number of threads that can access a resource or pool of
resources concurrently
That is understood and clear.
But I never got a chance to play with the overload of Wait which accepts a timeout integer, however - this seems to allow multiple threads get into the critical section although I've explicitly set semaphore not to allow more than one thread at a time:
private readonly SemaphoreSlim _mutex = new SemaphoreSlim(1);
private void Main()
{
Task.Run(() => DelayAndIncrementAsync());
Task.Run(() => DelayAndIncrementAsync());
}
private void DelayAndIncrementAsync()
{
_mutex.Wait(2000);
try
{
Console.WriteLine(0);
Thread.Sleep(TimeSpan.FromSeconds(5));
Console.WriteLine(1);
}
finally
{
_mutex.Release();
}
}
The first thread is entering the mutex zone, prints "0", waits 5 seconds, meanwhile after 2 seconds the other thread ALSO enters the critical section?
Question
Isn't it defeating the whole purpose of semaphore?
What are the real life scenarios which I would use this timeout, especially when the basic rule is -
"Semaphore = Limits the number of threads that can access a resource
or pool of resources concurrently
You need to check the return value of the wait. The Timeout based wait will try for 2 seconds to take the mutex then return. You need to check if the return value is true (i.e you have the mutex) or not.
Edit: Also keep in mind that the timeout based wait will return immediately if the semaphore is available, so you cant use this to prevent an infinite loop in the code via this technique.
private readonly SemaphoreSlim _mutex = new SemaphoreSlim(1);
void Main()
{
Task.Run(()=>DelayAndIncrementAsync());
Task.Run(()=>DelayAndIncrementAsync());
}
public void DelayAndIncrementAsync()
{
if (_mutex.Wait(2000))
{
try
{
Console.WriteLine(0);
Thread.Sleep(TimeSpan.FromSeconds(5));
Console.WriteLine(1);
}
finally
{
_mutex.Release();
}
} else {
//oh noes I don't have the mutex
}
}
Your misconception is that there is an implicit "mutex zone" which is not defined by you.
The overload of Wait which you are using returns a boolean value which tells you whether or not the mutex was successfully entered.
What you are doing in your example is entering the critical zone whether or not the thread has acquired the mutex, making it redundant.
Generally, you would want to use this overload in any situation where you want to try to enter a mutex but also have a fallback strategy in case that it is not currently possible to acquire the mutex within the allotted time.
This will make people cringe but using the timeout (and confirming it did timeout) is a good way to log and track deadlock bugs. Sure if you wrote your program correctly you wouldn't need these, but I've personally used this for this purpose which has saved me a lot of time.
So yes it does defeat the purpose (in most cases) if you let it timeout and then hit the critical section with multiple threads. But it can be useful to log or detect a deadlock bug.
There are also use cases where you want multiple threads to access the critical section, but only in specific scenarios. Eg it would not be fatal and simply be undesirable for it occur. Eg you aren't using the semaphore to stop a cross thread crash, but rather something else.

How do I find the other threads that send back the signal when one thread calls WaitOne?

One of the things I'm having a hard time to understand in multi-threaded programming is that fact that when one thread reaches a line that calls WaitOne(), how do I know which other threads are involved? Where or how can I find (or understand) how the WaitHandle receives the signal? For example, I'm looking at this code right now:
private void RunSync(object state, ElapsedEventArgs elapsedEventArgs)
{
_mutex.WaitOne();
using (var sync = GWSSync.BuildSynchronizer(_log))
{
try
{
sync.Syncronize();
}
catch(Exception ex)
{
_log.Write(string.Format("Error during synchronization : {0}", ex));
}
}
_mutex.ReleaseMutex();
_syncTimer.Interval = TimeBeforeNextSync().TotalMilliseconds;
_syncTimer.Start();
}
There are a few methods like this in the file (i.e RunThis(), RunThat()). These methods run inside a Windows service and are called when a Timer elapses. Each of these methods are called using different Timers and set up like this:
//Synchro
var timeBeforeFirstSync = TimeBeforeNextSync();
_syncTimer = new System.Timers.Timer(timeBeforeFirstSync.TotalMilliseconds);
_syncTimer.AutoReset = false;
_syncTimer.Elapsed += RunSync;
_syncTimer.Start();
I understand that when the Timer elapses, the RunSync method will run. But when it hits the WaitOne() line, the thread is blocked. But who is it waiting for? Which "other" thread will send the signal?
WaitHandle is an abstraction, as stated in the documentation:
Encapsulates operating system–specific objects that wait for exclusive access to shared resources.
You don't know which other threads are involved, but you do know which other code is involved by checking the usage of the handle (_mutex in your case). Every WaitHandle derived class inherits WaitOne, but what happens after successful wait and how it's get signalled is specific. For instance, in your example _mutex most probably is a Mutex class, so WaitOne acts like "wait until it's free and take ownership" while the ReleaseMutex acts like "release ownership and signal". With that in mind, it should be obvious what all these methods do - ensuring that while RunThis you cannot RunThat and vise versa.

Only need the first task, ignore the rest

I want to call a task at a specified interval. And avoid calling a new task unless the last has already completed.
private async void OnTimerTick(object sender, object e)
{
if (_criticalSection.IsEntered()) return; // only allow 1 at any given time, ignore the rest
using (var section = await _criticalSection.EnterAsync())
{
await update();
}
}
How do I achieve this? Any suggestions for a better pattern?
A critical section (like a Window's mutex) is for mutual exclusion: only allowing a single thread into a code path.
But that's not what you are trying to do: you need something that will tell you if something is happening.
A better approach would be a Manual Reset Event: set it (also know as signalled) at the start of the task and reset at the end. Then you can check if it is signalled by waiting on it with a timeout of zero for a normal Window's event, or with the applicable member for other types of event.
As this appears to be all in a single process a good starting point is System.Threading.ManualRestEventSlim. Used something like:
// One off initialisation somewhere at class scope
private static ManualResetEventSlim taskRunning = new ManualResetEventSlim();
private static object taskLock = new Object();
// code called from the timer, do in a lock to avoid race conditions with two
// or more threads call this.
lock (taskLock) {
if (!taskRunning.IsSet) {
StartTheTask(); // assuming this does not return until task is running.
}
}
// At the outermost scope of the code in the task:
try {
Debug.Assert(!taskRunning.IsSet); // Paranoia is good when doing threading
taskRunning.Set();
// Task impementation
} finally {
Debug.Assert(taskRunning.IsSet); // Paranoia is good when doing threading
taskRunning.Reset();
}
Another approach would be to always start the task, but have it check the event, if set then immediately exit. This would still need the lock to avoid races between the IsSet and Set() calls across threads. This second approach keeps the checking code together at the cost of briefly having another task running (unless that is common I would likely take this approach for the code locality).

How to block an operation until a condition is met?

I am running this code and it is using a fair amount of CPU even though it is doing absolutely nothing most of the time.
while (this.IsListening)
{
while (this.RecievedMessageBuffer.Count > 0)
{
lock (this.RecievedMessageBuffer)
{
this.RecievedMessageBuffer[0].Reconstruct();
this.RecievedMessageBuffer[0].HandleMessage(messageHandler);
this.RecievedMessageBuffer.RemoveAt(0);
}
}
}
What is the best way to block until a condition is met?
Use a WaitHandle.
WaitHandle waitHandle = new AutoResetEvent();
// In your thread.
waitHandle.WaitOne();
// In another thread signal that the condition is met.
waitHandle.Set();
You could also consider changing the interface of your class to raise an event when there is new data to be read. Then you can put your code inside the event handler.
Assuming you are using .NET 4, I'd suggest switching RecievedMessageBuffer to be a BlockingCollection. When you are putting messages into it, call it's Add method. When you want to retrieve a message, call it's Take or TryTake methods. Take will block the reading thread until a message is available, without burning CPU like your original example.
// Somewhere else
BlockingCollection<SomethingLikeAMessage> RecievedMessageBuffer = new BlockingCollection<SomethingLikeAMessage>();
// Something like this where your example was
while (this.IsListening)
{
SomethingLikeAMessage message;
if (RecievedMessageBuffer.TryTake(out message, 5000);
{
message.Reconstruct();
message.HandleMessage(messageHandler);
}
}
Above lines of code and specifically AutoResetEvent is available in version 3.5. So simple code like above with some minor correction is very effective because it works and close to foundation API. The correction should be
AutoResetEvent waitHandle = new AutoResetEvent(false);
Constructor with argument false makes WaitOne() to wait because AutoResetEven is not reset (false). There is not much advantage of using interface WaitHandle, so I would just use AutoResetEvent instead as it exposes method Set and WaitOne is quite verbose in this case. Most importantly, the constructor argument and should be false.

Creating a Loop to Pause a Script While a Callback Function Operates

I am currently using a third party component to handle telnet connections in .NET. I want it to be synchronous where I send a command to the receiving telnet server and then I get the response back as text or byte array. Only problem is that the component is not set up to do that. The component allows me to send commands to the server, but the response is returned via a function handle. So in essence, I need a way to pause the application while the handler does it's processing. Here is an example of how I plan to get around that issue:
static void Main(string[] args)
{
Telnet telCon = new Telnet();
telCon.OnDataIn += new Telnet.OnDataInHandler(HandleDataIn);
telCon.Connect(remoteHostStr);
while (true) ;
}
public static void HandleDataIn(object sender, TelnetDataInEventArgs e)
{
string responseStr = e.Text;
if (responseStr.Contains("Username:"))
{
((Telnet)sender).Send(System.Text.ASCIIEncoding.ASCII.GetBytes(username));
}
else if (responseStr.Contains("Password:"))
{
((Telnet)sender).Send(System.Text.ASCIIEncoding.ASCII.GetBytes(password));
}
}
The solution above will not work since the while will always run, but I will probably build a future version that uses some sort of global variable to track if the loop still needs to run. However, everything I have been taught about programming says this is very dirty. Can anyone think of another way around my dilemma?
Thanks,
Chris
Here is an example of using a ManualResetEvent to suspend execution (and delay program end) until your event handler says it's finished.
static ManualResetEvent finishGate;
static void Main(string[] args)
{
finishGate = new ManualResetEvent(false); // initial state unsignaled
Telnet telCon = new Telnet();
telCon.OnDataIn += new Telnet.OnDataInHandler(HandleDataIn);
telCon.Connect(remoteHostStr);
finishGate.WaitOne(); // waits until the gate is signaled
}
public static void HandleDataIn(object sender, TelnetDataInEventArgs e)
{
// handle event
if (processingComplete)
finishGate.Set(); // signals the gate
}
The WaitOne() method of ManualResetEvent also includes overrides that accept a timespan or number of milliseconds. It returns bool - true if it was signaled, false if it timed out. If you put that in a loop, you could have your main thread wake up every 30 seconds and perform some housekeeping tasks, but still have an instantaneous response when the gate is signaled.
Your while loop:
while(true) ;
will drive CPU usage to 100% (well, 100% of 1 core on a multicore machine) and leave it there, permanently.
This will starve other processes of CPU power, and may prevent the Telnet component from working at all because you've bypassed the message pump.
There are better ways, but without more information on what you're doing, it will be hard to advise you.
To begin, do you want a WindowsForms/WPF/Console application?
[And please, use comments to answer, not Answers.]
In general, when you really need to wait, use a WaitHandle. In this case, a ManualResetEvent would probably be what you need.
A better way would be to spawn the Telnet processing to another thread. That way you can get the main thread to wait for the telnet processing to complete.
Have a look here for some very good tutorials on threading.

Categories