2009-09-02 8 views
2

Как вы ограничиваете процессор цикла while?Как ограничить использование ЦП в цикле 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 вызывает эту задержку, как и должно быть.

Как я могу ограничить процессор, который это занимает? По какой-то причине мой диспетчер задач говорит, что для выполнения этой простой задачи требуется 50 процессоров, но, вероятно, это займет не более 1 или 2. Хотя менеджер говорит, что он занимает столько CPU, скорость моего компьютера не изменяется все, что странно, учитывая, что это двухлетний ноутбук.

Я не хочу каких-либо пользователей урод об этом, но, зная, как люди в эти дни ....

Во всяком случае, язык vb.net. Может кто-нибудь, пожалуйста, помогите мне?

Спасибо!

EDIT: Для того, чтобы уточнить, что код не внутри самого цикла в то время как, но вызов для подпрограммы, т.е. wait(1000)

+1

Рефакторинг. Серьезно, есть способы лучше построить: waithandles, callbacks и т. Д. –

+0

Дайте пример кода, пожалуйста? – Cyclone

+0

В каком контексте используется этот код? – 2009-09-02 21:11:27

ответ

7

Используйте событие таймера !!! Почти нет усилий процессора.

+0

Как я могу изменить свой секундомер в таймер? – Cyclone

+0

Коррекция: как измерить прошедшие миллисекунды по таймеру? – Cyclone

+0

Никогда не используйте таймер для ожидания. – 2009-09-02 21:05:24

5

Вы всегда могли выполнять какое-то сон между итерациями цикла ...

Я не знаком с VB.NET, но продолжительность 100-200 мс, вероятно, будет более чем достаточно, чтобы отказаться от использования ЦП.

Например:

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

Редактировать После некоторых исследований, я думаю, что функция вы хотите: System.Threading.Thread.Sleep()

+0

Err, на самом деле он должен ждать одну секунду, иначе он не будет функционировать. Понимаете, это игра. – Cyclone

+0

Итак, Sleep() для 1000 мс. –

+0

Он должен перезагрузить пользовательский интерфейс, пока он спит, хотя ..... – Cyclone

0

Ну, процессор всегда работает на 100%, когда он работает, поэтому единственный практический способ ограничить использование ЦП - запустить всплески или цикл и спать между ними.

Процессоры для ноутбуков обычно имеют некоторую технологию SpeedStep или equievalent, которая замедляет работу процессора, когда он не работает, но неразумно предположить, что ваше приложение будет иметь доступ к управлению, которое, по крайней мере, не напрямую. Вы можете косвенно повлиять на это, измерив использование ЦП и отрегулировав длину цикла работы и сна, чтобы получить желаемый результат.

+0

Почему downvote? Если вы не объясните, что вы не считаете правильным, оно не сможет улучшить ответ. – Guffa

+0

Потому что я думаю, что CPU здесь нечего делать. Нужно использовать прерывания, которые не оказывают заметного влияния на процессор, и это происходит через события, в этом случае событие таймера. –

4

Ваш код выполняет Application.DoEvents() постоянно в цикле while в течение времени, указанного в параметре time. Это будет потреблять одно ядро ​​вашего процессора, поэтому вы видите 50-процентное использование процессора (у вас есть двухъядерный процессор, правильно?). Это уродливый способ подождать. Вместо этого вы можете вызвать Thread.Sleep(), передав ему количество миллисекунд, которое вы хотите, чтобы ваш поток подождал.

Если вы хотите, чтобы ваше приложение оставалось отзывчивым, вы также могли бы отключить таймер и блокировать пользовательский интерфейс от любого действия до тех пор, пока таймер не начнет срабатывать.Нечто подобное (слегка тестировался):

// 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 
+0

Thread.Sleep() не обновляет пользовательский интерфейс, не так ли? – Cyclone

+0

И да, двухъядерный процессор. – Cyclone

+0

См. Мой код для реализации на основе таймера, которая поддерживает обновление пользовательского интерфейса. –

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 

Конечно, что-то более сложное можно построить в зависимости от того, что вы пытаетесь выполнить.

+0

Конечно, если он возобновит поток и обновит пользовательский интерфейс, это будет отлично. – Cyclone

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 милисекунд ,

Весело

0

Вы должны принять к сведению, если вы делаете это в основном потоке пользовательского интерфейса или нити вы отделились.

для потоков самый простой способ это просто Thread.Sleep (х миллисекунды)

На главном потоке пользовательского интерфейса Я предпочитаю использовать функцию DoEvents в vb.net и VB6, как это

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 

к вопросу об использовании процессора я смотрю на это так .... если вы сделаете только жесткий цикл, который нравится

while true 
end while 

я бы ожидал увидеть очень высокую загрузку процессора более чем на 50%, потому что поток пользовательского интерфейса трудно б блокировка на этом .... в большинстве случаев система Windows ограничивает использование процессора какой-либо данной программой, чтобы ее потоки не блокировали всю систему.

DoEvents гарантирует, что сообщения для сообщений Windows будут корректно реагировать и реагировать на них. Это также гарантирует, что сборщик мусора будет срабатывать вовремя.

Кроме того, если вы другие потоки раскручиваются от вашей UI.Thread вашего UI.Thread может реагировать на события, запускаемых с этих другими потоков ....

В таких случаях, когда ваши телефонные элементы управления формой из других потоков и do form.InvokeRequired подпрограмм сможет правильно реагировать.

Также Единственный раз, когда вы должны быть твердыми зацикливание на MainUI нити, когда она в ответ на какой-то активности пользователя, и вы должны положить ожидания в для пользователя, чтобы увидеть прогресс чего-то ....

Если это какой-то автоматический процесс, который всегда работает ... посмотрите на перенос его в другой поток.

Или если это что-то, что периодически запускается по таймеру или время, начинающееся с потока.

Кто-нибудь, пожалуйста, скажите мне, если я ошибаюсь, эти предположения ....

Не уверен, что о Используя белый как новый ManualResetEvent (False) wh.WaitOne (мс), как я никогда не слышал о том, что и есть не знаю, что это делает.

 Смежные вопросы

  • Нет связанных вопросов^_^