Delphi - корректировка времени ожидания потока - PullRequest
7 голосов
/ 07 июня 2009

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

Поскольку такая ситуация может возникать в нескольких потоках одновременно, я не хочу, чтобы мое приложение использовало 100% процессорного времени, когда эти потоки обрабатывают данные; Я также не хочу, чтобы все потоки боролись за процессорное время. Поэтому я вызываю функцию Sleep () в каждой итерации циклов в этих потоках.

Однако я не знаю, как настроить время сна. Я не хочу, чтобы петли длились вечно, поэтому период сна не может быть слишком долгим. Я установил его на 2 миллисекунды в каждой итерации (в каждом потоке) (почему 2 мс? - это хороший вопрос :)).

С другой стороны, я думал, что мог бы продлить время сна, но вызывать сон только один раз каждые n итераций (скажем, Sleep (100) каждые 50 итераций). Какой подход я должен выбрать? Один цикл повторения занимает около 30 мс каждый (без каких-либо снов).

Пожалуйста, сообщите.

Спасибо!
Мариуш.

Ответы [ 4 ]

9 голосов
/ 07 июня 2009

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

Если вы хотите, чтобы потоки спали, чтобы ограничить объем данных, которые они генерируют для потребителей, загляните в очереди производитель-потребитель. Сделайте так, чтобы потоки производителя просто блокировались, когда их очередь заполнена, таким образом вам вообще не нужно будет манипулировать временем.

Обратите внимание, что использование максимальной загрузки процессора, как правило, хорошо, особенно на современных процессорах. Даже на ноутбуках с коротким временем высокой нагрузки лучше, чем искусственно продлевать время, необходимое для выполнения вашей задачи, поскольку процессор / вся система быстрее смогут переходить в состояния с низким энергопотреблением.

3 голосов
/ 08 июня 2009

Вам лучше просто создавать потоки с низким приоритетом и позволить им работать без снов, иначе вы не используете всю мощность процессора. Например, в многоядерных / многопроцессорных системах. Или если ваша система на 100% простаивает: зачем ждать или спать?

Но если вам нужно некоторое время сна, обратите внимание, что sleep (1) ждет 10-15 мс (!) Из-за временного интервала Windows по умолчанию. Вы можете использовать timeBeginPeriod (1) модуля MMSystem.pas, чтобы установить разрешение 1 мс :-) (я использовал это для последовательной связи).

2 голосов
/ 07 июня 2009

Подходы могут быть лучше, чем использование sleep для управления вашими потоками. Поскольку ваш вызов базы данных может возвращать 1-1000 записей для обработки, возможно, имеет смысл разделить ваше приложение на два уровня, возможно, используя очередь сообщений для буферизации запросов. Ваше приложение может вызывать службу данных, а затем служба данных будет выполнять запрос и отправлять отдельные сообщения данных (или блоки сообщений и т. Д.) В очередь. Ваше приложение может затем создать столько потоков, сколько необходимо для обработки сообщений. Большее количество потоков означает более быструю обработку за счет ресурсов процессора, но вы можете настроить это, чтобы получить правильный баланс.

0 голосов
/ 17 июня 2016

используйте TThread.Sleep () из System.Classes вместо Sleep () из WinApi.Windows

// Winapi.Windows contains GetTickCount and Sleep
// System.Classes contains TThread (universal option) // TThread.GetTickCount() // TThread.Sleep()
uses System.Types, System.Classes, Vcl.Forms;

// тогда в вашем процессе используйте следующее

TThread.Sleep(0);

Application.ProcessMessages(); // clear all Vcl messages  // part of Vcl.Forms
CheckSynchronize(); // check all threaded events
...