2

你如何限制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 循环每秒运行一次,并且waitsub 会导致此延迟,因为它应该。

如何限制这占用的 CPU?出于某种原因,我的任务管理器说运行这个简单的任务需要 50 个 CPU,但它可能需要不超过 1 或 2 个。虽然经理说它需要那么多 CPU,但我的计算机速度并没有受到影响所有,考虑到它是一台使用了两年的笔记本电脑,这很奇怪。

我不希望任何用户对此感到害怕,但要知道这些天人们的状况......

无论如何,语言是vb.net。有人可以帮帮我吗?

谢谢!

编辑:澄清一下,该代码不在while循环本身内,而是对子例程的调用,即wait(1000)

4

7 回答 7

7

使用定时器事件!!!几乎没有cpu努力。

于 2009-09-02T20:14:35.213 回答
6

你总是可以在循环的迭代之间执行某种睡眠......

我不熟悉 VB.NET,但 100-200 毫秒的持续时间可能足以降低 CPU 使用率。

例如:

Do while (...)
    Application.blah();
    System.Threading.Thread.Sleep(150);
End

编辑经过一番研究,我认为您想要的功能是: System.Threading.Thread.Sleep()

于 2009-09-02T20:12:19.040 回答
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
于 2009-09-02T20:17:19.310 回答
0

好吧,CPU 在运行时总是以 100% 运行,因此限制 CPU 使用的唯一实用方法是运行突发或循环并在其间休眠。

笔记本电脑 CPU 通常具有一些 SpeedStep 技术或等效技术,当 CPU 不努力工作时会减慢它的速度,但假设您的应用程序可以访问控制它是不合理的,至少不能直接控制它。您可以通过测量 CPU 使用率并调整工作和睡眠周期的长度来间接影响它以获得所需的结果。

于 2009-09-02T20:17:11.340 回答
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

当然,可以根据您要完成的任务来构建更复杂的东西。

于 2009-09-02T21:04:05.503 回答
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 毫秒。

玩得开心

于 2013-04-14T15:59:05.313 回答
0

您应该注意您是在主 UI 线程还是您已分拆的线程中执行此操作。

对于线程,最简单的方法就是 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.Thread 中分离出来,您的 UI.Thread 可以响应从这些其他线程触发的事件......

在这种情况下,您从其他线程调用表单控件并执行 form.InvokeRequired 例程将能够正确响应。

此外,您应该在 MainUI 线程上进行硬循环的唯一时间是当它响应某些用户活动并且您需要等待用户查看某些事情的进度时......

如果它是某种始终在运行的自动化进程......希望将其移动到另一个线程。

或者,如果它在计时器上定期运行或启动线程的时间。

如果我对这些假设有误,请告诉我......

不确定 Using wh As New ManualResetEvent(False) wh.WaitOne(ms) 因为我从未听说过,也不知道它是做什么的。

于 2017-02-03T05:14:33.670 回答