C# 是";while(true)“;通常用于永久性螺纹?

C# 是";while(true)“;通常用于永久性螺纹?,c#,multithreading,C#,Multithreading,我对编码比较陌生;我的大部分“工作”都只是简单的GUI应用程序,只为一件事工作,所以我不需要太多线程 无论如何,关于线程,我想知道的一件事是,如果你想让一个线程永远活着,以完成它正在做的任何工作(处理、等待输入等等),那么像这样格式化它是正常的吗: while (true) { // do stuff Thread.Sleep(1000); } (或者类似的东西)。。。?或者这不安全,如果可能的话应该避免吗?是的,你就是这么做的 但通常是这样的: bool keepRunnin

我对编码比较陌生;我的大部分“工作”都只是简单的GUI应用程序,只为一件事工作,所以我不需要太多线程

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

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

(或者类似的东西)。。。?或者这不安全,如果可能的话应该避免吗?

是的,你就是这么做的

但通常是这样的:

bool keepRunning = true;

...

while(keepRunning){
}
因为有时你可能希望有人/事能够阻止你。

此外,你还可以使用。在这种情况下,我们不必使用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());
    }
}
使用:

控制台输出:

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

Timer stop.

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

Timer stop.

正如一些附加信息一样,典型的无结尾循环使用

for(;;)
{
 ...
} 

因为在循环中没有进行比较。执行线程时,最好检查循环是否结束的标志。

理想情况下,您希望线程在有工作要做时处于“可运行”状态,而在无事要做时处于“休眠”状态

最好使用互斥(互斥)、信号量和条件变量等对象来实现这一点,这些对象为线程提供机制,以便在可能需要其他线程执行某些操作时唤醒其他线程

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

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

您还必须注意,访问共享内容的线程会避免


我不能给出任何C#特定的见解,但我知道C#为您提供了一些工具来帮助您。

更详细地说,如果线程正在休眠,当操作系统启动线程时,它只会检查它是否仍在休眠,如果是的话,然后只给出它的时间片

如果你不睡觉,做一些类似的事情

while (true)
{
    if (workAvailable)
        {
        doWork();       
        }
}
然后,即使workAvailable为false,它也会一直旋转,直到操作系统停止它,占用整个切片,什么也不做。很明显,这样效率会低一点


如前所述,互斥体、信号量等的处理可能会变得更加复杂,但它们很快就会变得复杂,因此您可能需要使用它们来解决特定的问题。

我也遇到过同样的问题,并尝试了几种方法,注意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%)。您只需等待一个永远不会发生的重置事件。低CPU%的等待时间,优雅。此外,您还可以通过调用“resetEvent.Set()”来终止无限等待,甚至从另一个线程…

所以这是常见的做法?可以如果要关闭Thread.Abort(),它有什么问题?只需好奇.Thread.Abort就可以了,但它会导致异常,并且可能会中断您关心的某些事情。使用“keepRunning”变量,您可以优雅地完成所做的任何事情(尽管不会立即完成)。中止有其问题,因为它可能导致数据结构保持不稳定,并且由于线程正在释放它们,其他线程也可能变得不稳定。(假设它们在搬运时被锁定,因此释放时不稳定)。这就是为什么该方法在Java中被弃用的原因,至少。keepRunning通常会声明为volatile,以便其他线程可以将其设置为false以停止当前线程。另外,不要忘记将keepRunning设置为volatile!(volatile bool keepRunning=true;)有效,但它是一种可怕的C-ism,不必要地神秘。
ManualResetEvent resetEvent = new ManualResetEvent(false);
resetEvent.WaitOne(); // WINNER: 4% cpu in my case, and very elegant also.