Is "while (true)" usually used for a permanent thread?
Asked Answered
C

6

14

I'm relatively new to coding; most of my "work" has been just simple GUI apps that only function for one thing, so I haven't had to thread much.

Anyway, one thing I'm wondering about threading is if you want to keep a thread alive forever to do whatever job it's doing (processing, waiting for input, whatever), is it normal to format it like so:

while (true) {
    // do stuff
    Thread.Sleep(1000);
}

(or something along those lines)...? Or is this not safe and should it be avoided if possible?

Castellany answered 15/8, 2009 at 11:55 Comment(0)
P
24

Yep, that's what you do.

But typically it's like:

bool keepRunning = true;

...

while(keepRunning){
}

Because sometimes you may like to have someone/something else to have the ability to stop you.

Parahydrogen answered 15/8, 2009 at 11:57 Comment(8)
So it is common practice? Okay. What are the problems with say, Thread.Abort() if you wanted to close that? Just curious.Castellany
Thread.Abort is fine but it'll cause an exception, and it may interrupt something that you care about finishing. With the 'keepRunning' variable it lets you finish whatever you were doing gracefully (though it won't result in an immediate finish).Parahydrogen
Abort has its problems since it can cause data structures to remain unstable, and since the thread is releasing them other threads could become unstable too. (supposed they were locked while being handled, therefore unstable when released). That's why the method was made deprecated in Java, at least.Pansy
keepRunning would usually be declared as volatile so a different thread can set it to false to stop the current thread.Galligan
@Henk in what language? java? Yes, agreed but in c#: I see nothing wrong with it.Parahydrogen
Several discussions on SO, here is just one #710570Godspeed
Also don't forgot to make keepRunning volatile! (volatile bool keepRunning = true;)Pahang
keepRunning = false; myThread.Join(); is the exit i use. Join forces the calling thread to wait untill the thread you want to stop is finished, this is handy when using the IDisposable interface and making sure after Dispose() has ifnished execution the thread really has stopped.Fertilization
E
3

Additionally You can use System.Threading.Timer. In this case, we don't have to use the Sleep method. Simple example:

public sealed class TimerTask
{
    private Timer _timer;
    private int _period;

    public TimerTask(int period)
    {
        _period = period;
        _timer = new Timer(new TimerCallback(Run), "Hello ....", Timeout.Infinite, period);
    }

    public void Start()
    {
        _timer.Change(0, _period);
    }

    public void Stop()
    {
        _timer.Change(Timeout.Infinite, Timeout.Infinite);
    }

    private void Run(Object param)
    {
        Console.WriteLine(param.ToString());
    }
}

Use:

public static class Program
{
    [STAThread]
    static void Main(String[] args)
    {
        TimerTask task = new TimerTask(1000);
        Console.WriteLine("Timer start.");
        task.Start();
        Console.ReadLine();
        Console.WriteLine("Timer stop.");
        task.Stop();
        Console.ReadLine();
        Console.WriteLine("Timer start.");
        task.Start();
        Console.ReadLine();
        Console.WriteLine("Timer stop.");
        task.Stop();
        Console.ReadLine();
    }
}

Console output:

Timer start.
Hello ....
Hello ....
Hello ....

Timer stop.

Timer start.
Hello ....
Hello ....

Timer stop.
Explanation answered 15/8, 2009 at 12:51 Comment(0)
E
3

To elaborate a bit more, if a thread is sleeping, when the OS comes along to activate the thread, it will just check to see if it's still sleeping and if so, then just yield its timeslice.

If you leave out the Sleep and do something like

while (true)
{
    if (workAvailable)
        {
        doWork();       
        }
}

then even if workAvailable is false it will keep spinning until the OS stops it, taking up its entire slice doing nothing. Obviously that's a little more inefficient.

You can get even more complex as needed with mutexes, semaphores and whatnot, as mentioned above, but things get complex quickly with those, so you might want to use them to solve a particular problem.

Endmost answered 15/8, 2009 at 14:8 Comment(0)
K
2

Ideally you want the thread to be "runnable" when it has work to do, and "sleeping" when there is nothing to do.

This is best done with objects like mutual exclusions (mutexes), semaphores and condition variables, which provide mechanisms for threads to wake other threads up when there may be something for them to do.

Just doing a timed sleep is inefficient, because a short sleep means the thread wastes time waking up to check if there's work to do, while a long sleep means the thread might be asleep while there's work to be done. Usually this is not a big deal but if the code deals with large volumes of requests or data things don't go so well.

A basic model works like this: Thread A puts objects in a queue. Thread B removes an object from the queue, performs an action, and repeats. If there are no objects in the queue, thread B will remain asleep until an object arrives.

You must also be careful that threads which access shared stuff avoid race conditions.

I can't give any C#-specific insight, but I know that C# gives you some tools to help you out.

Kiushu answered 15/8, 2009 at 13:14 Comment(0)
T
1

Just as some additional info, typical none ending loops use

for(;;)
{
 ...
} 

as there is no compare done in the loop. When doing threads it is best to check a flag if the loop to end or not though.

Theologize answered 15/8, 2009 at 12:58 Comment(1)
Works, but it is an awful C-ism that is unnecessarily cryptic.Godspeed
P
1

I had the same problem and tried several methods, keeping an eye on the CPU % which in my case was really important. Here the results:

while (true) {} //this is the worst CPU-consuming one: 30% in my case.

The above, in terms of performance, is the worst (takes more CPU % than any other method, 30% on my project, on my pc). Much better the next one:

while (true) {thread.sleep(1);} //5% cpu, in my case

The above is good in terms of CPU % (around 5% in my case), but not very much elegant:

Console.Readline(); //4% cpu in my case, but for very specific projects

The above is usable only in specific cases, and it's good if you have a console .net application running on background that will never be able to capture a keypress. Still not much elegant, but takes around 4% of CPU in my particular case.

ManualResetEvent resetEvent = new ManualResetEvent(false);
resetEvent.WaitOne(); // WINNER: 4% cpu in my case, and very elegant also.

The above, in my opinion, is the best one: elegant and low CPU consuming (4% in my case). You simply wait for a resetEvent that will never happen. Low CPU% on waiting, and elegant. Also, you can make terminate the infinite waiting by calling "resetEvent.Set()", even from another thread...

Purpura answered 13/6, 2020 at 16:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.