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