Гость
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Прервать алгоритм по Esc / 25 сообщений из 43, страница 1 из 2
15.11.2021, 12:56
    #40112050
Maxim Rusov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
Есть множество алгоритмов которые что-то считают в основном потоке клиента. Нужно чтобы они прерывались по Esc. Внутри алгоритма периодически вызывается CheckInterrupt. Как его лучше реализовать? Пробовал 2 варианта:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
  procedure CheckInterrupt;
  var
    vMsg :TMsg;
  begin
    while PeekMessage(vMsg, 0, WM_KeyFirst, WM_KeyLast, pm_Remove) do
      if (vMsg.Message = WM_KeyDown) and (vMsg.WParam = VK_Escape) then
        raise EBreak.Create('');
  end;


и
Код: pascal
1.
2.
3.
4.
5.
  procedure CheckInterrupt;
  begin
    if GetAsyncKeyState(VK_Escape) <> 0 then
      raise EBreak.Create('');
  end;


Оба работают, но оба имеют недостатки. Вариант с PeekMessage "съедает" все нажатия, что иногда не годится (например алгоритм может запускаться как раз для обработки нажатий. Например, что то типа автодополнения). Вариант с GetAsyncKeyState - тоже имеет заморочки. Например, он может пропускать нажатия, если CheckInterrupt вызывается недостаточно часто.

Может можно как то просканировать очередь сообщений на предмет клавиатурных нажатий, но не извлекая их из очереди? Например, для консоли есть PeekConsoleInput, но для оконной очереди я аналога не нашел.

И да, программа - на Delphi. :)
...
Рейтинг: 0 / 0
15.11.2021, 13:30
    #40112063
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
...
Рейтинг: 0 / 0
15.11.2021, 13:42
    #40112067
Maxim Rusov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
Не в тему. Мне не нужен глобальный hotkey. Который все равно не придет без цикла обработки сообщений.
...
Рейтинг: 0 / 0
15.11.2021, 13:53
    #40112072
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
Maxim RusovКак его лучше реализовать?

Лучше таки загнать его в поток. Но проктостоматологи могут обойтись хоткеем на
пункте меню + ProcessMessages.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
15.11.2021, 13:53
    #40112073
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
Maxim Rusov,

Т.е. у тебя это все в основном потоке "интерактивно" без ProcessMessages работает?

Тогда не трахай мозги себе и окружающим и переноси расчеты в потоки.
...
Рейтинг: 0 / 0
15.11.2021, 14:03
    #40112080
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
Ну и для знатных проктостоматологов есть еще вариант посадить хук SetWindowsHookEx(WH_KEYBOARD,,) на всю винду.
...
Рейтинг: 0 / 0
15.11.2021, 14:07
    #40112081
Maxim Rusov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
То, что должно работать в потоках - работает в потоках. Никто не загоняет в потоки любой алгоритм, который _может_ работать долго. Например - у меня текстовый редактор, файл может быть большой. Его открытие и любая блочная операция _может_ работать долго и должна быть прерываемой. Но никто в здравом уме не будет делать многопоточный текстовый редактор.

Все кто на любой вопрос про длительные процессы отвечают "используй потоки" - обычно бла-бла, сами даже понятия не имеют, насколько это сложно.
...
Рейтинг: 0 / 0
15.11.2021, 14:12
    #40112082
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
Maxim Rusovобычно бла-бла, сами даже понятия не имеют, насколько это сложно.

На практике это обычно гораздо проще, чем думают чайники. Главное - потоки
запускать, используя beginthreadex, а не TThread. Хотя да, у чайников обычно есть проблема с пониманием, что процедура потока может начать (и даже закончить) выполняться раньше, чем вызывающая программа её дойдёт до следующей после beginthreadex строчки.

Вариант с шорткатом на экшоне, устанавливающем переменную "прервись", и
ProcessMessages я уже назвал.
...
Рейтинг: 0 / 0
15.11.2021, 14:52
    #40112092
Maxim Rusov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
Dimitry Sibiryakov
На практике это обычно гораздо проще, чем думают чайники.

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

Dimitry Sibiryakov
Вариант с шорткатом на экшоне, устанавливающем переменную "прервись", и ProcessMessages я уже назвал.


В первом посте я привел 2 работающих варианта, и объяснил чем они меня не устраивают. Вариат "с шорткатом на экшоне" как и любой другой требующий вызова ProcessMessages, будет обладать теми же недостатками что и первый CheckInterrupt, только хуже
...
Рейтинг: 0 / 0
15.11.2021, 15:09
    #40112096
Fr0sT-Brutal
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
OnKeyUp => Cancel := True;
Process => while not Cancel do begin Something; App.ProcessMsgs; end
...
Рейтинг: 0 / 0
15.11.2021, 15:14
    #40112097
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
Maxim RusovВариат "с шорткатом на экшоне" как и любой другой требующий вызова
ProcessMessages, будет обладать теми же недостатками что и первый
CheckInterrupt, только хуже

Ваши объяснения недостатков первого варианта было слишком невнятным, так что я
ничего не понял. Кто съедает, куда съедает, зачем съедает. Первый вариант
работает так как написан, а написал он именно с PM_REMOVE.

Если "алгоритм может запускаться как раз для обработки нажатий", то
ProcessMessages это именно то, что нужно, ибо доставит ему (алгоритму) эти нажатия.

PS: Таки да, и открытие файла и поиск в тексте с лёгкостью загоняются в потоки.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
15.11.2021, 15:21
    #40112100
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
Dimitry Sibiryakov
Главное - потоки запускать, используя beginthreadex, а не TThread.
А мне больше решения из System.Threading нравяться.
...
Рейтинг: 0 / 0
15.11.2021, 15:23
    #40112102
Maxim Rusov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
Dimitry Sibiryakov
Кто съедает, куда съедает, зачем съедает.

"Съедает" пользовательский ввод. Пользователь нажал "A" - запустился алгоритм поиска по "А" чтобы вывести автодополнение. Пользователь не глядя нажал "B" - алгоритм его съел в процессе CheckInterrupt. Пользователь ругается - нажатие потерялось.

Dimitry Sibiryakov
...и открытие файла и поиск в тексте с лёгкостью загоняются в потоки...

А модификация текста?
...
Рейтинг: 0 / 0
15.11.2021, 15:31
    #40112103
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
Dimitry Sibiryakov
Главное - потоки запускать, используя beginthreadex, а не TThread.
Почему?
...
Рейтинг: 0 / 0
15.11.2021, 15:33
    #40112104
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
Maxim Rusov"Съедает" пользовательский ввод. Пользователь нажал "A" - запустился алгоритм
поиска по "А" чтобы вывести автодополнение. Пользователь не глядя нажал "B" -
алгоритм его съел в процессе CheckInterrupt. Пользователь ругается - нажатие
потерялось.

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

Maxim RusovА модификация текста?
Легко. Главное решить заблокировать ли действия пользователя на это время или
как-то разруливать их параллельно, поскольку текст, дёргающийся при модификации,
обычно раздражает пользователя, пытающегося его параллельно набирать. Но есть и
исключения, как, например, автоперевод хираганы/катаканы в канджи при наборе.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
15.11.2021, 15:38
    #40112105
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
_Vasilisk_Почему?

Ясность мысли. В мозгу не возникает иллюзии "поток это объект". Впрочем,
TThread.CreateAnonymousThread.Start (именно в таком виде) тоже сойдёт если без
лямбд.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
15.11.2021, 16:17
    #40112114
Maxim Rusov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
Dimitry Sibiryakov
Не так не надо бездумно копипастить код в который кто-то другой с совсем другими намерениями поместил PM_REMOVE.

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

Dimitry Sibiryakov
Maxim RusovА модификация текста?

Легко. Главное решить заблокировать ли действия пользователя на это время или
как-то разруливать их параллельно
Это совсем не главное. Главное что теперь у вас в разных потоках модифицируются общие структуры данных и это нужно разруливать критическими секциями. Иначе у вас не текст будет дергаться, а вполне конкретные AV посыпятся.
...
Рейтинг: 0 / 0
15.11.2021, 16:24
    #40112117
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
Maxim Rusovпричина PM_REMOVE в этом коде очевидна, без нее проверка зациклится.

Почему она должна зациклиться? Да, если в очереди будут нажатия других кнопок,
они будут сканироваться раз за разом, но сам по себе цикл сканирования очереди
завершится, когда переберёт все клавиатурные сообщения в ней. Ах да, там же
кто-то забыл его ограничить только клавиатурными сообщениями...

Maxim RusovГлавное что теперь у вас в разных потоках модифицируются общие
структуры данных и это нужно разруливать критическими секциями.
Зависит от природы "общих структур данных". Но даже если и так, у вас какая-то
личная ненависть к критическим секциям?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
15.11.2021, 16:24
    #40112118
Zelius
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
Maxim Rusov,

если алгоритм обрабатывает нажатия, значит где-то еще есть PeekMessage/GetMessage, значит надо сделать PeekMessage с no remove и если там Esc, то вынуть из очереди и прервать, а если нет, то пусть дальше обрабатывается.
Но вообще, согласен, выглядит как правильнее в поток убрать.
...
Рейтинг: 0 / 0
15.11.2021, 17:00
    #40112127
Maxim Rusov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
Dimitry Sibiryakov

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

Как же он завершится, когда он будет постоянно возвращать первое сообщение в очереди?
Dimitry Sibiryakov
Ах да, там же кто-то забыл его ограничить только клавиатурными сообщениями...

Почему? Там же стоит WM_KeyFirst, WM_KeyLast.
Maxim Rusovу вас какая-то личная ненависть к критическим секциям?
Проанализировать все алгоритмы на предмет из какого потока они могут вызываться, определить набор ресурсов, которые нужно защитить критическими секциями, правильно расставить эти секции, чтобы не нарваться на Deadlock... Что вы там говорили насчет чайников?
И главное - зачем? Алгоритм все равно не распараллеливается и является асинхронным. Даже исходная задача с прерыванием по Esc - не решается, собственно.
...
Рейтинг: 0 / 0
15.11.2021, 17:07
    #40112130
Maxim Rusov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
Zelius
значит надо сделать PeekMessage с no remove и если там Esc, то вынуть из очереди и прервать, а если нет, то пусть дальше обрабатывается

Еще раз. Алгоритм запустился по нажатию кнопки "А" и что-то долго считает. Возможно, завис, его не я пишу - это скриптовой алгоритм. Пользователь жмет "BC" - смотрит, а буквы не появляются. Жмет Esc, чтобы алгоритм прервать. Если в очереди сидят "B" и "C" то про нажатие Esc нельзя узнать, не выбрав предыдущие нажатия и тем самым разрушив очередь. Ну - или я не знаю, как это сделать.
...
Рейтинг: 0 / 0
15.11.2021, 17:16
    #40112131
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
Maxim RusovКак же он завершится, когда он будет постоянно возвращать первое сообщение в
очереди?

После того, как главный цикл его это сообщение обработает. Вы же не хотите
повесить всю программу на всё время работы "алгоритма", не так ли?..

Maxim RusovДаже исходная задача с прерыванием по Esc - не решается, собственно.

Как раз решается: нажатие Esc штатным образом обрабатывается циклом выборки
сообщения и может делать всё, что нужно, включая сигнализацию алгоритму о
необходимости прерваться.

Maxim RusovПроанализировать все алгоритмы на предмет из какого потока они
могут вызываться, определить набор ресурсов, которые нужно защитить критическими
секциями, правильно расставить эти секции, чтобы не нарваться на Deadlock... Что
вы там говорили насчет чайников?

Даже чайник справится с определением "любое обращение к глобальному объекту" и
"только непосредственно на время обращения к этому объекту".
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
15.11.2021, 17:20
    #40112132
Zelius
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
Maxim Rusov,

считывай все сообщения, а затем посылай их обратно )
...
Рейтинг: 0 / 0
15.11.2021, 17:22
    #40112133
Zelius
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
Maxim Rusov,

еще костыль - делаешь отдельный поток который раз в 100мс проверяет GetAsyncKeyState и ставит флаг в основном ))
...
Рейтинг: 0 / 0
15.11.2021, 17:22
    #40112134
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Прервать алгоритм по Esc
Maxim RusovАлгоритм запустился по нажатию кнопки "А" и что-то долго считает. Возможно,
завис, его не я пишу - это скриптовой алгоритм. Пользователь жмет "BC" -
смотрит, а буквы не появляются.

А теперь то же самое, но с потоками: пользователь жмёт "ВС" и они появляются,
Esc жать не надо, проблема даже не возникла, все счастливы.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Прервать алгоритм по Esc / 25 сообщений из 43, страница 1 из 2
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]