С Новым годом! Форум программистов, компьютерный форум, киберфорум
Delphi для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.79/29: Рейтинг темы: голосов - 29, средняя оценка - 4.79
68 / 33 / 11
Регистрация: 18.07.2014
Сообщений: 263

Быстрая функция Sleep

31.05.2021, 11:55. Показов 6968. Ответов 21

Студворк — интернет-сервис помощи студентам
Перемещаю мышь по кривым безье за определённое время. Очень часто вызывается Sleep(1) много раз, при этом накладные расходы на вызов Sleep огромные.Таким образом 100 раз по Sleep(1) длятся полторы секунды, а не около 100 милисекунд.

Чем можно заменить винапишную Sleep чтобы всё было не так печально?
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
31.05.2021, 11:55
Ответы с готовыми решениями:

функция sleep()
Создайте функцию sleep(), приостанавливающую работу компьютера на столько секунд, сколько указано в аргументе функции. Перегрузите sleep()...

Функция sleep()
Добрый день! Помогите мне пожалуйста: Создать функцию sleep(), приостанавливающая работу компьютера на столько секунд, сколько указано...

Функция sleep
Доброго дня, подскажите пожалуйста. Имеется функция: function sleep(miliseconds) { var currentTime = new Date().getTime(); ...

21
Модератор
4115 / 2347 / 807
Регистрация: 15.11.2015
Сообщений: 9,354
31.05.2021, 12:05
Цитата Сообщение от KOTOM Посмотреть сообщение
накладные расходы на вызов Sleep огромные.
Нет.

Цитата Сообщение от KOTOM Посмотреть сообщение
Таким образом 100 раз по Sleep(1) длятся полторы секунды, а не около 100 милисекунд.
Если не включено повышенное разрешение таймера, то шаг таймера равен 16 мс. То есть, и Sleep(1) и Sleep(15) дадут задержку 16 мс. А вот Sleep(16) может дать плавающую задержку, то 16, то 32 мс. Отсюда логично следует, что 100 штук Sleep(1) даст задержку в 1600 мс.

Включение повышенного разрешения:
Delphi
1
  TimeBeginPeriod(1); // Включает точность таймера 1 мс.
Теперь Sleep(1) даст задержку 1 мс.
Delphi
1
  TimeEnd(1); // Выключает повышенное разрешение.
При этом, разрешение таймера будет наивысшим из тех, которые запросили приложения. И будет оставаться повышенным, пока есть хоть одно приложение, повысившее разрешение таймера.

PS. Обычно, браузеры включают повышенное разрешение.
2
31.05.2021, 12:15

Не по теме:

Цитата Сообщение от AzAtom Посмотреть сообщение
Обычно, браузеры включают повышенное разрешение
Хм-м... Не знал...

0
Модератор
4115 / 2347 / 807
Регистрация: 15.11.2015
Сообщений: 9,354
31.05.2021, 12:31
Ошибся. Выключать надо
Delphi
1
TimeEndPeriod(1); // Выключает повышенное разрешение.
Добавлено через 2 минуты

Не по теме:

D1973, случайно заметил было, когда пытался вывести анимацию. То Sleep(1) срабатывал быстро, то медленно. В итоге нашёл, что быстро срабатывал при запуске оперы.

0
Злостный нарушитель
 Аватар для Verevkin
10249 / 5676 / 1262
Регистрация: 12.03.2015
Сообщений: 26,311
31.05.2021, 12:48
Вариант без Sleep() надо или и так сойдёт?
0
Модератор
4115 / 2347 / 807
Регистрация: 15.11.2015
Сообщений: 9,354
31.05.2021, 13:01
А зачем перемещать каждую 1 мс? Сама мышь обычно двигается с интервалом 10-16 мс.

Добавлено через 24 секунды
И с таймером не лучше ли будет?
0
68 / 33 / 11
Регистрация: 18.07.2014
Сообщений: 263
31.05.2021, 13:25  [ТС]
AzAtom, Не знал этого, спасибо. Но всё равно не помогло. Написал такой пробный код.
Delphi
1
2
3
4
5
6
7
8
9
10
procedure TForm1.FormCreate(Sender: TObject);
var bt,et:Cardinal; i:Integer;
begin
TimeBeginPeriod(1);
bt:=timeGetTime;
for i:=0 to 999 do Sleep(1);
et:=timeGetTime;
TimeEndPeriod(1);
ShowMessage(IntToStr(et-bt));
end;
Выдаёт 1800мс времени вместо примерно 1000.

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

Добавлено через 22 минуты
На просторах сети нашёл вот такую функцию. Работает точно, но прилично нагружает процессор.

Delphi
1
2
3
4
5
6
7
8
9
10
11
function SleepMicro(mksec:cardinal):boolean;
var freq:int64;
count,count2,delta:int64;
begin
  result:=QueryPerformanceFrequency(freq);
  result:=QueryPerformanceCounter(count);
  if not result then exit;
  delta:=(mksec*freq) div 1000000;
  count2:=count+delta;
  while count2>count do QueryPerformanceCounter(count);
end;
0
Модератор
4115 / 2347 / 807
Регистрация: 15.11.2015
Сообщений: 9,354
31.05.2021, 14:25
KOTOM, ну как бы в windows не гарантируется точность Sleep. Если нужна точность, то надо считывать системное время и учитывать миллисекунды оттуда.

Добавлено через 3 минуты
Цитата Сообщение от KOTOM Посмотреть сообщение
Работает точно, но прилично нагружает процессор.
Естественно, будет нагружать. Это не выход.

Лучше всего, думаю, по таймеру с интервалом 15 мс считывать системное время и уже опираться на его показания. Это будет точно по времени и минимально по нагрузке процессора. Если хочется внутри одного цикла, то опять же, Sleep(15).
1
68 / 33 / 11
Регистрация: 18.07.2014
Сообщений: 263
31.05.2021, 14:39  [ТС]
AzAtom, Я пробовал делать так. Перемещаю мышь типа виртуально, накапливая нужную задержку до 16мсек. Когда накопленная задержка становится 16мсек или больше, то я перемещаю мышь уже фактически, делаю Sleep(16) и начинаю всё заново. Но почему-то при этом у меня начинает вырубаться монитор, да и помогает не сильно. В дебагере смотрел, всё правильно работает, откуда глюки - непонятно.
0
Модератор
4115 / 2347 / 807
Регистрация: 15.11.2015
Сообщений: 9,354
31.05.2021, 14:46
KOTOM, интересно. А можно глянуть код, который вырубает монитор?
Слегка заинтересовался. Если будет время, вечером набросаю свой вариант перемещения мыши по заданным координатам.
0
Злостный нарушитель
 Аватар для Verevkin
10249 / 5676 / 1262
Регистрация: 12.03.2015
Сообщений: 26,311
31.05.2021, 14:54
На всякий случай оставлю это здесь.
0
68 / 33 / 11
Регистрация: 18.07.2014
Сообщений: 263
31.05.2021, 15:24  [ТС]
AzAtom,

Не по теме:

Эмуляцию кода который вырубает монитор скинул в личку. Причём там важнен и сам SendInput и манипуляции с мышью одновременно. По отдельности монитор не вырубается. И насколько я понял важно именно перемещение мыши туда, где она и так сейчас есть.



Поменял местами Sleep и MouseMove в том своём коде который куски по 16мсек отсчитывает и всё стало лучше, монитор вырубаться перестал и точность немножно поднялась.
0
31.05.2021, 15:33
 Комментарий модератора 
KOTOM, Согласно правилам форума все обсуждение в тематических разделах ведутся только в теме, так то или публикуйте код здесь или придется Вас забанить.
0
68 / 33 / 11
Регистрация: 18.07.2014
Сообщений: 263
31.05.2021, 15:43  [ТС]
Puporev, Пожалуйста. Я то думал это будет оффтоп.

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
type SPI_MouseThreshholdsInfo=record Treshold1, Treshold2, Acceleration:Integer; end;
 
function GetMouseSpeed:integer;
begin
SystemParametersInfo(SPI_GETMOUSESPEED, 0, @Result, 0);
end;
 
function SetMouseSpeed(Speed:integer):boolean;
begin
Result:=SystemParametersInfo(SPI_SETMOUSESPEED,1,Pointer(Speed),0);
end;
 
function GetMouseThreshholds:SPI_MouseThreshholdsInfo;
begin
SystemParametersInfo(SPI_GETMOUSE, 0, @Result, 0);
end;
 
procedure SendInputMouseMove(X,Y:Integer);
var SI:TInput; Speed:integer; mt,mt_bak:SPI_MouseThreshholdsInfo;
begin
Speed:=GetMouseSpeed;
mt_bak:=GetMouseThreshholds;
mt.Treshold1:=0; mt.Treshold2:=0; mt.Acceleration:=0;
SystemParametersInfo(SPI_SETMOUSE,0,@mt,0);
SetMouseSpeed(10);
 
SI.mi.dx:=x;
SI.mi.dy:=y;
SI.mi.dwFlags:=MOUSEEVENTF_MOVE;
 
SI.Itype:=INPUT_MOUSE;
SI.mi.dwExtraInfo:=GetMessageExtraInfo;
SendInput(1,SI,SizeOf(TInput));
 
SystemParametersInfo(SPI_SETMOUSE,0,@mt_bak,0);
SetMouseSpeed(Speed);
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var i:Integer;
begin
for i:=0 to 999 do SendInputMouseMove(0,0);
end;
0
Модератор
4115 / 2347 / 807
Регистрация: 15.11.2015
Сообщений: 9,354
31.05.2021, 16:49
KOTOM, а зачем тут устанавливать скорость мыши? Это же относится только к физической мышке? А программно можно подавать SendInput как хочется.
0
68 / 33 / 11
Регистрация: 18.07.2014
Сообщений: 263
31.05.2021, 17:04  [ТС]
AzAtom, Я этот код писал несколько лет назад, не помню уже. Проблемы возникли с девайсом usb2kbd. Скорее всего с эмуляционными функциями тоже были проблемы. У меня там целый ворох функций для перемещения мыши и везде если стоит относительное перемещение мыши, то это перемещение обёрнуто изменениями скорости. В том примере который я скинул нет фрага MOUSEEVENTF_ABSOLUTE, значит перемещение относительное, а так как там стоит 0,0 то оно ещё и в ту же точку где находится курсор.

Кстати у вас монитор тоже выключается?
0
Модератор
4115 / 2347 / 807
Регистрация: 15.11.2015
Сообщений: 9,354
31.05.2021, 17:32
Цитата Сообщение от KOTOM Посмотреть сообщение
относительное перемещение мыши
А, понятно. Я не использовал относительное перемещение, не вижу смысла в нём в подобных программах. Лучше абсолютное.

Цитата Сообщение от KOTOM Посмотреть сообщение
у вас монитор тоже выключается?
Ещё не смотрел. Попозже попробую.
0
68 / 33 / 11
Регистрация: 18.07.2014
Сообщений: 263
31.05.2021, 17:38  [ТС]
AzAtom, Относительное перемещение нужно например в играх, где курсор всегда как бы в одном месте. Как пример могу привести например Arcanum. Там с мышью вообще всё плохо, а если делать GetCursorPos то он всегда в 799:599.
0
Модератор
4115 / 2347 / 807
Регистрация: 15.11.2015
Сообщений: 9,354
01.06.2021, 13:51
Лучший ответ Сообщение было отмечено KOTOM как решение

Решение

Вот такую штуку сделал. Тут нет настроек параметров мыши и монитор не вырубается:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    SpinEdit1: TSpinEdit;
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }
    FCoorda: array of TPoint;
    procedure AddCoord(Value: TPoint);
    procedure ClearCoord;
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  AutoScroll := false;
  Button1.Caption := 'Генерировать круг';
  Button2.Caption := 'Генерировать параболу';
  Button3.Caption := 'Старт';
  Label1.Caption := 'Длительность'#13#10'перемещения, мс:';
  SpinEdit1.Value := 3000; // Длительность движения мыши в миллисекундах
end;
 
procedure TForm1.AddCoord(Value: TPoint);
begin
  SetLength(FCoorda, Length(FCoorda) + 1);
  FCoorda[High(FCoorda)] := Value;
end;
 
procedure TForm1.ClearCoord;
begin
  SetLength(FCoorda, 0);
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var
  i, cx, cy, r: integer;
begin
  // Добавить координаты окружности
  ClearCoord;
  cx := Screen.Width  div 2;
  cy := Screen.Height div 2;
  r := 200;
  for i := 0 to 199 do
    AddCoord(Point(cx + Round(Sin(i/100*Pi)*r), cy - Round(Cos(i/100*Pi)*r)));
end;
 
procedure TForm1.Button2Click(Sender: TObject);
var
  i, cx, cy: integer;
begin
  // Добавить координаты параболы
  ClearCoord;
  cx := Screen.Width  div 2;
  cy := Screen.Height div 2;
  r := 200;
  for i := -100 to 100 do
    AddCoord(Point(cx + i*2, cy - Round(i*i/30) + 100));
end;
 
procedure SetMouseCoord1(Value: TPoint);
var
  ti:TINPUT;
begin
  ti.Itype := 0;// (0 - mouse, 1 - keyboard, 2 - hardware)
  ti.mi.dx := Round(65535/(Screen.Width -1)*Value.X); // 0 - 65535 - full screen
  ti.mi.dy := Round(65535/(Screen.Height-1)*Value.Y); // 0 - 65535 - full screen
  ti.mi.mouseData := 0; // 0 if not whell or xbutton events
  ti.mi.dwFlags := MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_MOVE;
  ti.mi.time := 0; // 0 - used system timestamp
  ti.mi.dwExtraInfo := 0;
  SendInput(1, ti, sizeof(tagINPUT));
end;
 
procedure TForm1.Button3Click(Sender: TObject);
var
  i: integer;
  dt, st, ct: double;
begin
  if Length(FCoorda) = 0 then
    Exit;
  dt := SpinEdit1.Value / Length(FCoorda);
  dt := dt/24/60/60/1000; // Перевод миллисекунд в формат TDateTime
  TimeBeginPeriod(1);
  st := Now;
  for i := 0 to High(FCoorda) do begin
    SetMouseCoord1(FCoorda[i]);
    while Now < (st + dt*i) do // Ожидание нужного момента времени по системным часам
      Sleep(1);
  end;
  TimeEndPeriod(1);
end;
 
end.
0
68 / 33 / 11
Регистрация: 18.07.2014
Сообщений: 263
01.06.2021, 16:40  [ТС]
AzAtom, Практически тоже самое что и у меня если выбрать абсолютные нормализованные координаты, но у меня задержка расчитывается исходя из длины куска кривой безье, а не количества точек. А почему используется Now а не timeGetTime?

С моим кодом монитор вырубается?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
01.06.2021, 16:40
Помогаю со студенческими работами здесь

функция Sleep() ?
Кто знает , какое значение точно нужно указывать что ты бы единица отчета соответствовала секунде? Я ставлю Sleep(70), но решил...

функция sleep()
Помогите разобраться. Я изучаю &quot;С&quot; и использую программу Microsoft Visual C++ 2010 Express. Все учебные программки консольные с расширением...

Реализована ли функция sleep
на плюсах есть функция sleep,есть ли аналог в c#?

Функция Sleep() C++ Builder
Дело в том что функция Sleep() не правильно работает. Мне надо чтобы при нажатии на Image, картинка двигалась влево, а потом обратно. При...

Как работает функция sleep()
Из описания функции sleep(): Допустим задано 3600 сек = 1 час: Вопросы: - Что происходит во время исполнения функции?...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru