如何限制while循环的CPU?
在这种情况下,while循环内的代码:
Private Sub wait(ByVal time)
Dim sw As New Stopwatch
sw.Start()
Do While sw.ElapsedMilliseconds < time And StillOpen = True
Application.DoEvents()
Loop
sw.Stop()
End Sub
但现在,这是问题所在。这个循环允许while循环每秒运行一次,而wait
sub会导致这种延迟,应该如此。
如何限制占用的CPU?出于某种原因,我的任务经理表示它需要50个CPU来运行这个简单的任务,但它应该不会超过1或2.虽然经理说它占用了那么多的CPU,但我的计算机速度并没有受到影响所有这些都是奇怪的,因为它是一台已有两年历史的笔记本电脑。
我不希望任何用户对此感到害怕,但是知道这些日子的人是怎样的......
无论如何,语言是vb.net。有人可以帮助我吗?
谢谢!
编辑:澄清一下,该代码不在while循环本身内,但是对子程序的调用是,wait(1000)
答案 0 :(得分:7)
使用计时器事件!!!几乎没有cpu努力。
答案 1 :(得分:6)
你总是可以在循环的迭代之间执行某种睡眠......
我不熟悉VB.NET,但持续时间100-200ms可能足以降低CPU使用率。
例如:
Do while (...)
Application.blah();
System.Threading.Thread.Sleep(150);
End
编辑经过一番研究,我认为你想要的功能是:System.Threading.Thread.Sleep()
答案 2 :(得分:4)
您的代码在while循环中不断执行Application.DoEvents(),持续时间为time
参数中指定的持续时间。这将占用你的CPU的一个核心,这就是为什么你看到50%的处理器使用率(你有一个双核处理器,对吗?)。这是一种难看的等待方式。你可以调用Thread.Sleep(),传递你希望线程等待的毫秒数。
如果您希望应用程序保持响应,您可能还会关闭计时器,并阻止UI执行任何操作,直到计时器触发。像(轻度测试)的东西:
// constructor or designer code
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
timer.Tick += new EventHandler(timer_Tick);
void Wait(int interval)
{
timer.Interval = interval;
timer.Start();
BlockUIOperations(); // implement yourself
}
void timer_Tick(object sender, EventArgs e)
{
timer.Stop();
EnableUIOperations(); // implement yourself
}
这是我尝试翻译成VB:
'' Add a Timer object to the form named "Timer".
'' Hook its Tick event to Timer_Tick
Private Sub Wait(ByVal interval As Integer)
Timer.Interval = interval
Timer.Start()
BlockUIOperations() '' implement yourself
End Sub
Private Sub Timer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer.Tick
Timer.Stop()
EnableUIOperations() '' implement yourself
End Sub
答案 3 :(得分:0)
嗯,CPU在运行时始终以100%运行,因此限制CPU使用率的唯一实用方法是运行突发或循环和睡眠。
笔记本电脑CPU通常具有一些SpeedStep技术或相当的技术,当它不努力工作时会降低CPU的速度,但假设你的应用程序可以控制它,至少不是直接控制它是不合理的。您可以通过测量CPU使用率来间接地影响它,并调整工作和睡眠周期的长度以获得所需的结果。
答案 4 :(得分:0)
如果您不介意阻止当前线程,可以使用WaitHandle。
Public Sub Wait(ByVal ms As Integer)
Using wh As New ManualResetEvent(False)
wh.WaitOne(ms)
End Using
End Sub
Sub Main()
Console.WriteLine("Hello World!")
Wait(5000)
Console.WriteLine("Good-Bye!")
End Sub
当然,根据你想要完成的事情,可以构建更复杂的东西。
答案 5 :(得分:0)
这是一个完美的VB.net睡眠替代品。现在我的控制台应用程序没有被报告为无响应,因为我没有睡眠命令!
只需在模块上方添加Imports System.Threading,并将其置于子主页
上方Public Sub Wait(ByVal ms As Integer)
Using wh As New ManualResetEvent(False)
wh.WaitOne(ms)
End Using
End Sub
然后,在您的子主页中,使用
wait(100)
暂停你的应用100毫秒。
玩得开心
答案 6 :(得分:0)
你应该记下你是在主UI线程中执行此操作还是在旋转的线程中执行此操作。
对于Threads,最简单的方法是Thread.Sleep(x miliseconds)
在主UI线程上,我倾向于在vb.net和vb6中使用DoEvents函数,就像这样
Public Sub TimeKiller(byval secondstowait as integer)
dim tmptime as datetime = datetime.now
do while datetime.now < dateadd("s",secondstowait,tmptime)
Application.Doevents
end while
End Sub
关于CPU使用率的问题,我这样看......如果你只做一个类似
的硬循环while true
end while
我希望看到超过50%的CPU使用率非常高,因为UI线程在这方面很难阻塞....在大多数情况下,Windows系统将限制任何给定程序的CPU使用率,以便其线程不会阻止整个系统。
DoEvents确保Windows消息泵正确启动并响应正确。它还确保垃圾收集器按时触发。
此外,如果你有其他线程从你的UI中分离出来。更换你的UI.Thread可以响应从这些其他线程发起的事件....
在这种情况下,您的调用表单从其他线程控制并执行form.InvokeRequired例程将能够正确响应。
另外,你应该在MainUI线程上进行硬循环的唯一一次是当它响应某些用户活动时,你需要等待用户看到某些事情的进展....
如果某种自动化流程始终在运行......请将其移至另一个线程。
或者,如果它是在计时器上定期运行的某个东西或启动线程的时间。
有人请告诉我,如果我在这些假设上错了......
不确定使用wh作为新的ManualResetEvent(False)wh.WaitOne(ms),因为我从未听说过,也不知道那是做什么的。