Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Чем заменить sleep().  (Прочитано 21689 раз)
0 Пользователей и 1 Гость смотрят эту тему.
pupk1n
Гость
« : 25-03-2008 12:16 » 

Если таймером то как? какие есть способы вообще, пишите желательно с кодом...
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 25-03-2008 12:19 » 

по идее, зависит от цели применения и от того, какая точность достаточна

я в разных случаях пользуюсь

1)Sleep
2)::GetTickCount
3)таймер WM_TIMER
Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #2 : 25-03-2008 13:41 » 

А чем слип не подходит? Те ты хочешь остановить процесс/тред на определённое количество единиц времени? Или?
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
DrGluck
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 25-03-2008 14:05 » 

А истчо есть мультимедийный таймер ( TimeSetEvent, TimeKillEvent и т.д. читай MSDN).
Вроде он точно отсчитывает тики, но в нем была какая то засада, не помню щас какая.

GetTickCount и WM_TIMER гарантируют только, что задержка произойдет НЕ МЕНЬШЕ чем на время, указанное в таймере (и не меньше 50 мс). Но в силу некоторых причин задержка может быть гораздо больше. Но если пофиг, то...
Записан

Good user - dead user
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #4 : 25-03-2008 14:19 » 

Да вы подождите, ведь принципиально не ясно, что он хочет? Ведь ни ни GetTickCount и WM_TIMER не останавливают процесс так, как это делает слип.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
DrGluck
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 26-03-2008 07:29 » 

Согласен  Ага
Записан

Good user - dead user
Вахмурка
Помогающий

ru
Offline Offline
Пол: Мужской
Программист


WWW
« Ответ #6 : 26-03-2008 08:14 » 

 А нельзя использовать показания системного таймера в милисекундах? Можно в цикле переодически вызвать sleep, а в условии цикла проверять сколько действительно прошло времени. Если прошло столько сколько нам надо, выходим из цикла. Для этого только надо чтобы время на которое останавливает поток sllep было гарантировано меньше необъодимого нам времени, а если точнее сказать, то время на которое sleep останавливает поток определяет точность с которой будет засечён промежуток времени. Я думаю этого можно добится. Улыбаюсь
« Последнее редактирование: 26-03-2008 08:22 от Вахмурка » Записан

Программа – это мысли спрессованные в код.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #7 : 26-03-2008 08:47 » 

Вахмурка, а я так и делаю, где нельзя применить WM_TIMER, но надо реагировать на события

Код:

//начало блока
#define def_Sleep_BEGIN(delta_Ms) \
{\
DWORD __dwdDelta_Ms=(delta_Ms);\
DWORD __dwdCurrTicks=0;\
DWORD __dwdEndTicks;\
def_Sleep_RESET;\
__dwdCurrTicks=GetTickCount();\
for(;__dwdCurrTicks<__dwdEndTicks;__dwdCurrTicks=GetTickCount())\
{

//конец блока
#define def_Sleep_TIMEOUT_or_BREAK(needbreak) \
if(needbreak)break;\
}\
}

//перезапуск таймера
#define def_Sleep_RESET __dwdEndTicks=GetTickCount()+(__dwdDelta_Ms)

-----------------------
применение:

def_Sleep_BEGIN()
{
//опрос и break если надо
//(__dwdEndTicks-__dwdCurrTicks) == прошедшее время

Sleep(1);

//а если вдруг решили перезапустить таймер - вызываем
//def_Sleep_RESET __dwdEndTicks
}
def_Sleep_TIMEOUT_or_BREAK(0) //сюда можно и переменную bool подставить


правда, быстрее 10...16 мс не среагирует
« Последнее редактирование: 26-03-2008 14:50 от Алексей1153++ » Записан

DrGluck
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 26-03-2008 14:06 » 

правда, быстрее 10...16 мс не среагирует

В этом и вопрос. Прямо щас по-быстрому сваял прогу, в которой затестил Sleep и таймер.
Результаты слегка удивляют:

now := GetTickCount;
Sleep(100);
now2 := GetTickCount;

(now2 - now) = стабильно МЕНЬШЕ 100. Примерно 92-95.  Не может быть...

Надо покопаца в литературе...
Записан

Good user - dead user
DrGluck
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 27-03-2008 06:03 » 

Привет всем!
Столкнулся со следующей проблемой. При задании предположим Sleep(5) на одних машинах происходит задержка 5мс, на других 10мс, на третих 16мс.
Причем 2000 Professional всегда работает коректно ,на  XP  - по разному  5мс и 10мс. А на 2000 Server - всегда 16 мс. Изменяя время ожидания,экспериментальным
путем определил, что существует дискретная величина отсчета времени. На одних машинах она установлена в 1, на других в 10 или 16.
Sleep(4)         4     ---     10     --    16
Sleep(5)         5     ---     10     --    16
Sleep(12)      12     ---     20     --    16
Sleep(22)      22     ---     30     --    32
Sleep(60)      60     ---     60     --    64
Может кто-то знает где находится эта дискретная величина и как ее устанавливать?
Заранее благодарен. Юра .


Вот и я примерно об этом. Тока Sleep(100) себя так странно ведет. Сегодня скачет от 93 до 103.
Sleep(50) = ~47
Sleep(30) = 32
Sleep(200) = 200-202
Sleep(500) = 500 стабильно.

Вот почему при маленьких значениях получаеца 4, 16, 32 это понятно - связано с квантом времени приложения и зависит от операционки.
А вот почему иногда меньше бывает, лично мне пока не ясно.
Мелкософты клянутся, что: The Sleep function suspends the execution of the current thread for at least the specified interval.

A value of zero causes the thread to relinquish the remainder of its time slice to any other thread of equal priority that is ready to run. If there are no other threads of equal priority ready to run, the function returns immediately, and the thread continues execution. (Ну дык это если Sleep(0).)

Если кто знает ответ - пишите. А то вот так пользовался всю жизнь Sleepом мимодумно, а оно вона как оказалось А черт его знает...
Записан

Good user - dead user
DrGluck
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 27-03-2008 07:11 » 

Гм. Чем дальше, тем страньше.
Проверял в дельфи 5 и в 2006.

Результаты:
В дельфи 5 Sleep(x) стабильно показывает результаты не меньше x. При этом четко видно разделение на кванты примерно по 16 мс.
В 2006 стабильно меньше x. Но тоже кванты видны.

текст:

procedure TForm1.Timer1Timer(Sender: TObject);
var
  now1, now2: DWORD;
  s: DWORD;
begin
  s := SpinEdit1.Value;
  now1 := GetTickCount;
  Sleep(s);
  now2 := GetTickCount;
  Memo1.Lines.Add(IntToStr(now2 - now1));
end;

Таймер настроен на 1000. Спин эдит изменяет параметр слипа.

Может я где ошибаюсь?
Вроде Sleep в обеих дельфях одинаково задекларирован. Я думал, что в 2006 использовали SleepEx. Но нет, вроде.
И GetTickCount заявлен одинаково. Х.з. короче.
Записан

Good user - dead user
zubr
Гость
« Ответ #11 : 27-03-2008 09:10 » 

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

ru
Offline Offline
Пол: Мужской
Программист


WWW
« Ответ #12 : 27-03-2008 09:22 » 

... Это да. Неисповедимы пути системных процессов.
Записан

Программа – это мысли спрессованные в код.
DrGluck
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #13 : 27-03-2008 09:46 » 

Не, господа, вы не поняли суть проблемы. Я понимаю што винда, многозадачность и бла бла бла... Но, во первых, я иногда пользуюсь слипом, и хотелось бы ясности. Тем более, судя по этой теме, вариантов как организовать задержку на короткое время немного (вообще, у меня только мультимедийный таймер отсчитывал тики по 1 мс).

Почему задержка БОЛЬШЕ я понимаю.
Но какого фига Sleep дает задержку МЕНЬШЕ в дельфи 2006?

Если бы мелкософты написали что нибудь типа такого "процесс продолжает выполняться, если в системе нет другого процесса равного приоритета, который не находится в режиме Idle". Но ведь нет такого в MSDN.
Я ж подчеркнул The Sleep function suspends the execution of the current thread for at least the specified interval. (MSDN)
В этом непонятка, а вы меня за пионера приняли и объясняете очевидные вещи.

zubr, а вот объясни эту непонятку? А?

З.Ы.
XP SP2. Щас на 2003 попробую.
Записан

Good user - dead user
zubr
Гость
« Ответ #14 : 27-03-2008 10:08 » 

DrGluck, ты как запускал свои тесты? Из среды разработки (в отладке) или независимо?
Записан
Вахмурка
Помогающий

ru
Offline Offline
Пол: Мужской
Программист


WWW
« Ответ #15 : 27-03-2008 10:31 » 

 А если попробовать при разных приоритетах процесса( не потока )?
Записан

Программа – это мысли спрессованные в код.
DrGluck
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #16 : 27-03-2008 11:05 » 

1. На 2003 все четко и красиво для д5 и д2006. Т.е. кванты по 16.
2. Запускал и под отладкой и так просто.
3. Приоритеты не сильно изменяют интервал. При Sleep(5) для "Ниже нормального" начинается череда значений 0,15,0,15,0,15 в зависимости от загрузки системы. Для высоких приоритетов нулей больше.

Может у меня gluck какой?  Ага

З.Ы.
Вообще возможно и глюк. Перезагрузка приводит к нормальной работе обоих приложений. Потом опять начинаеца хрень. От чего зависит пока не понял. Может от направления ветра? На серваке 2003 все нормально. Попробую дома еще сегодня.

Предлагаю пока закончить обсуждение. На днях подойду к этой непонятке с SoftIce в руках. Тогда может отпишусь о результатах.
« Последнее редактирование: 27-03-2008 11:37 от DrGluck » Записан

Good user - dead user
DrGluck
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #17 : 28-03-2008 07:49 » new

В общем так:

Sleep работает нормально, как и должно быть. Т.е. явно прослеживаются кванты времени приложения.

Sleep(1-15) >= 16 мс
Sleep(16-31) >= 32 мс
Sleep(32-47) >= 48 мс
и т.д.
при больших значениях немного меняется, например Sleep(500) дает 500, а не 512 как можно было ожидать. Вероятно там сказывается загруженность системы. А может чего другое...

Но, есть тревожная новость: при запущенном дельфи 2006 слип начинает дурить примерно как я вчера написал.
При этом не важно запускаю я программу под отладкой или просто из под винды. Главное, что дельфи запущено в системе.
Вероятно это связано с их отладчиком.
MSVS такого эффекта не дает.
SoftIce не проверял, т.к. система свежая еще DriverStudio не ставил. Может сегодня проверю.

Т.е. резюмирую: слипом можно пользоваться когда точность нужна в пределах 20 мс (для XP SP2, не уверен, что на других системах тоже самое). Но с отладкой могут возникнуть проблемы (если точность имеет значение).

З.Ы.
Спасибо товарищу zubr за то что навел на мысль, а то я сначала тупанул и не подумал, что эффект может быть из за отладчика.
Записан

Good user - dead user
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines