“while(true)”通常用于永久线程吗?

时间:2009-08-15 11:55:44

标签: c# multithreading

我对编码比较陌生;我的大多数“工作”都只是简单的GUI应用程序,只能用于一件事,所以我没有必要进行多少操作。

无论如何,我想知道线程的一件事是,如果你想让一个线程永远活着去做它正在做的任何工作(处理,等待输入,等等),那么格式化它是正常的:

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

(或沿着这些方向的东西)......?或者这是不安全的,如果可能的话应该避免吗?

6 个答案:

答案 0 :(得分:24)

是的,这就是你的所作所为。

但通常情况如下:

bool keepRunning = true;

...

while(keepRunning){
}

因为有时候你可能想让别人/别人有能力阻止你。

答案 1 :(得分:4)

再详细说明一下,如果线程处于休眠状态,当操作系统出现以激活线程时,它只会检查它是否仍处于休眠状态,如果是,则只是产生其时间片。

如果你忽略了睡眠并做了类似

的事情
while (true)
{
    if (workAvailable)
        {
        doWork();       
        }
}

然后即使workAvailable为false,它也会继续旋转,直到操作系统停止它,占用整个切片。显然效率低一点。

如上所述,您可以根据需要使用互斥锁,信号量等等进行更复杂的处理,但事情会很快变得复杂,因此您可能希望使用它们来解决特定问题。

答案 2 :(得分:3)

此外,您可以使用System.Threading.Timer。在这种情况下,我们不必使用Sleep方法。简单的例子:

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());
    }
}

使用:

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();
    }
}

控制台输出:

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

Timer stop.

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

Timer stop.

答案 3 :(得分:2)

理想情况下,您希望线程在有工作要做时“可运行”,并且在没有任何事情要做时“休眠”。

最好使用互斥(互斥),信号量和条件变量等对象,这些对象提供了线程在可能有某些东西可以执行时唤醒其他线程的机制。

只是进行定时睡眠效率低下,因为短暂的睡眠意味着线程浪费时间醒来检查是否有工作要做,而长时间睡眠意味着线程可能在完成工作时睡着了。通常这不是什么大问题,但如果代码处理大量请求或数据,事情就不会那么顺利。

基本模型的工作原理如下:线程A将对象放入队列中。线程B从队列中删除对象,执行操作并重复。如果队列中没有对象,则线程B将保持睡眠状态,直到对象到达为止。

您还必须小心访问共享内容的线程避免使用race conditions

我不能提供任何C#特定的洞察力,但我知道C#为您提供了一些工具来帮助您。

答案 4 :(得分:1)

正如一些额外的信息,典型的无结束循环使用

for(;;)
{
 ...
} 

因为在循环中没有进行比较。在执行线程时,最好检查一个标志,如果循环结束或不结束。

答案 5 :(得分:0)

我遇到了同样的问题,并尝试了几种方法,请注意CPU%,这对我来说非常重要。结果如下:

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

就性能而言,以上是最差的(比任何其他方法占用更多的CPU%,在我的项目上,在我的PC上为30%)。下一个更好:

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

上面的CPU%(在我的情况下约为5%)方面不错,但不是很优雅:

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

以上内容仅在特定情况下可用,如果您有一个在后台运行的控制台.net应用程序永远无法捕获按键,则非常有用。仍然不够优雅,但在我的特定情况下占用大约4%的CPU。

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

我认为以上是最好的方法:优雅且CPU消耗低(在我的情况下为4%)。您只需等待一个不会发生的resetEvent。等待时CPU%较低,且优雅。另外,您甚至可以从另一个线程调用“ resetEvent.Set()”来终止无限等待。