2

我有一个程序在 3 个独立的计时器之间不断地启动。

我的应用程序的主线程有一个 while 循环,它不断检查全局变量是否已设置为 true,如果已设置,它将停止一个计时器并启动另外两个计时器 - 一个连续,另一个自动停止它,如果它不是t 命令以任何理由停止。

此 while 循环的条件为 (1==1),因此它永远运行。

在任务管理器 (XP) 中,我看到我的程序在或多或少空闲的系统上使用了 50% 的 cpu。

有没有办法通过降低while循环的速度或其他方式来减少这个数字?

谢谢。

4

7 回答 7

11

有没有办法通过降低while循环的速度或其他方式来减少这个数字?

只是停止做一个繁忙的循环。有更好的方法来协调线程之间的事件。考虑使用Monitor.Wait/PulseAutoResetEvent/ ManualResetEvent。基本上,设置全局变量的线程应该发出信号表明它已经这样做了。或者,如果您的主线程不做任何其他事情,为什么不添加一个普通的 C# 事件,以便每当更改变量时,都会引发事件并采取适当的操作?

于 2012-04-09T08:49:52.647 回答
6

您的程序执行忙等待,这是一种不好的做法。您应该更改逻辑,以便阻止某种同步原语(也称为等待句柄)而不是循环。

阻塞等待句柄不是 UI 线程的选项,因此您必须总共创建三个线程并实现如下方案:

  1. UI 线程根本不关心其他线程要做什么。没有循环,没有睡眠,没有阻塞。
  2. 新的“控制器”线程将启动现有的“工作者”线程,然后立即阻塞(例如,在未发出信号的事件上)。它将保持在这种状态,不消耗 CPU,直到事件发出信号(即“worker”完成)。
  3. “工人”线程将运行它的过程,然后发出事件信号。
于 2012-04-09T08:50:31.753 回答
4

有没有办法通过降低while循环的速度或其他方式来减少这个数字?

是的,您可以插入对Thread.Sleep(n). 粒度约为 20 毫秒。

但更好的选择是使用 Waithandle。
您的主线程将在句柄上等待,并且计时器代码的结束将发出信号唤醒它。

于 2012-04-09T08:50:26.007 回答
2

您需要让威胁休眠给定的毫秒数。查看 Thread.sleep() 函数并将其放在您的 while 循环中。

于 2012-04-09T08:50:01.177 回答
2

减慢这样一个循环的最简单方法是添加一个 System.Threading.Thread.Sleep(100); 对于每次迭代,该进程将休眠 100 毫秒,并且不再使用 50% 的 CPU。

于 2012-04-09T08:50:19.747 回答
2

您可以使用 Threads 而不是 Timer,它比 Thread 更昂贵。或者请检查您在开始另一个之前停止的时间的线程状态。您可以通过减少代码逻辑来提高性能。

希望这会帮助你。:)

于 2012-04-09T08:51:35.673 回答
0

虽然这里的答案每个人都没有错,但它们并没有真正解决很多关于while(true)循环的问题,这就是事实while(1==1)

首先,即使循环在你的应用程序使用的整个过程中都在运行,你也会想在某个时候停止它,比如当用户退出你的应用程序时,因为如果你有一个带有恒定循环的线程,即使用户关闭 UI 窗口,进程将一直保持到线程退出(从不在 while true 循环中)或直到用户变得明智并从任务管理器中关闭它。

您可以通过在 while 条件检查中放置一个真正的条件来解决这个问题,该检查引用循环外的可访问属性。

例子:

private bool RequestExit = false;
private Thread MyLoopThread;
private void MyLoop()
{
  while (!RequestExit)
  {
    //Do stuff!
    Sleep(1);
  }
}
public void StartLoop()
{
  RequestExit = false;
  MyLoopThread = new Thread(MyLoop);
  MyLoopThread.Start();
}
public void StopLoop()
{
  RequestExit = true;
}

那是最基本的,甚至没有避免双重启动或双重关闭事件。

一个更简洁的方法是设置一个你想要汇集的任意间隔,10ms 左右应该对几乎任何实时事件都很好,并触发一个在该间隔触发的方法。

private Timer DoStuffTimer;
private void DoStuffMethod(object obj = null)
{
  //Do stuff!
}
public void StartLoop()
{
  DoStuffTimer = new Timer(DoStuffMethod,null,10,10);
}
public void StopLoop()
{
  DoStuffTimer.Dispose();
}
于 2015-03-24T20:00:15.263 回答