How to limit CPU usage in a while loop

How do you limit the processor of the while loop?

In this case, the code inside the while loop:

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

      

But here's the problem. This loop allows the while loop to run every second, once every second, and sub wait

causes that delay as it should.

How can I limit the CPU it takes up? For some reason, my task manager says that it takes 50 processors to complete this simple task, but it probably won't take more than 1 or 2. Although the manager says it takes up that much CPU, my computer's speed doesn't change all that strange considering this is a two year old laptop.

I don't want any users to cheat on this, but knowing how people are these days ....

In any case, the language is vb.net. Can someone please help me?

Thank!

EDIT: To clarify, the code is not inside the while loop itself, but the call to the subroutine is, i.e. wait(1000)

+2


source to share


7 replies


Use timer event !!! Almost no processor effort.



+7


source


You can always do some kind of sleep in between loop iterations ...

I'm not familiar with VB.NET, but 100-200ms duration will probably be more than enough to get away with CPU usage.

For example:



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

      

Edit . After some research, I think you need a function: System.Threading.Thread.Sleep ()

+5


source


Your code continuously executes Application.DoEvents () in a while loop for the time specified in the parameter time

. This will consume one core of your cpu, so you see 50 percent cpu usage (you have a dual core processor, right?). It's an ugly way to wait. Instead, you can call Thread.Sleep () passing it the number of milliseconds that you want your thread to wait.

If you'd like to keep your app responsive, you could also disable the timer and block the UI from any action until the timer starts running. Something like (lightly tested):

// 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
}

      

Here's my attempt at translating to 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

      

+4


source


Well, the CPU is always running 100% when it is running, so the only practical way to limit CPU usage is to run bursts or loops and sleep in between.

Laptop processors tend to have some sort of SpeedStep or equievalent technology that will slow down the processor when it is not running, but it is not reasonable to assume that your application will have control access, which, at least not directly. You can indirectly influence this by measuring CPU usage and adjusting the work and sleep cycle lengths to get the desired result.

0


source


If you don't mind blocking the current thread, you can use 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

      

Of course, something more complex can be built depending on what you are trying to accomplish.

0


source


It is the perfect sleep replacement solution for VB.net. Now my console app is NOT reported as unresponsive since I have no sleep commands!

Just add Imports System.Threading above your module and place this just above your main one

Public Sub Wait(ByVal ms As Integer)

   Using wh As New ManualResetEvent(False)
        wh.WaitOne(ms)

    End Using
End Sub

      

Then in your main function use

wait(100) 

      

to pause your app for 100 milliseconds.

Good luck

0


source


You should take note if you are doing this on the main UI thread or the thread you have allocated.

For threads, the easiest way is just Thread.Sleep (x miliseconds)

In the main UI thread, I usually use the DoEvents function in vb.net and vb6 like this

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

      

When it comes to CPU usage, I look at it like this: if you only do a hard loop like

while true
end while

      

I would expect a very high cpu utilization rate to exceed 50% because the UI thread is heavily blocked by this .... in most cases Windows will limit cpu usage to any given program so that its threads do not block the entire system.

DoEvents ensures that messages on Windows messages will respond correctly and respond correctly. This also ensures that the garbage collector is triggered on time.

Also if you have other threads related to your UI. Try your UI.Thread can react to events fired from these other threads ....

In cases like this, when your calling form controls from other threads and makes the form. InvokeRequired routines will be able to respond correctly.

Also, the only time you have to be hard-looping in the MainUI thread is when it is reacting to some user interaction and you need to expect the user to see the progress of something ....

If it's some kind of automatic process that always works ... look at transferring it to another thread.

Or if it is something that periodically runs on a timer or a time starting from a thread.

Someone please tell me if I am wrong with these assumptions ....

Not sure about using WH-New ManualResetEvent (False) wh.WaitOne (ms), which I have never heard of and have no idea what it does.

0


source







All Articles