Помогите пож-та, решить такую проблему:
есть основной поток, т.е. создавший главное окно.
Он решает какую-то задачу и задумался надолго.
На клавиши, да и на другие события не реагирует.
Юзеру же необходима возможность отмены той задачи,
которой занимается основной поток (например, построение отчетов)
Он нажимает ESC и хочет оменить всё.
Так вот я создаю 2-ой поток, присоединяю
очередь ввода основного потока к этому
и вхожу в цикл GetMessage. Насколько я понимаю,
все сообщения ввода клавиатурного теперь должны попасть в очередь
2-го потока и он уже отменит задачу.
Выглядит все примерно так:
procedure TBreakThread.Execute;
var
msg: TMsg;
begin
if not AttachThreadInput(MainThreadID,SecThreadId,true) then
exit;
while GetMessage(msg, 0, 0, 0) do begin
case msg.message of
WM_KEYDOWN : какое-то действие
end;
end;
end;
Так вот никаких сообщений GetMessage не возвращает. Непонятно почему.
Здравствуйте, Begemote, Вы писали:
B>Помогите пож-та, решить такую проблему: B>есть основной поток, т.е. создавший главное окно. B>Он решает какую-то задачу и задумался надолго. B>На клавиши, да и на другие события не реагирует. B>Юзеру же необходима возможность отмены той задачи, B>которой занимается основной поток (например, построение отчетов) B>Он нажимает ESC и хочет оменить всё. B>Так вот я создаю 2-ой поток, присоединяю B>очередь ввода основного потока к этому B>и вхожу в цикл GetMessage. Насколько я понимаю, B>все сообщения ввода клавиатурного теперь должны попасть в очередь B>2-го потока и он уже отменит задачу.
По-моему у вас как-то всё наизнанку получается. Почему бы не дать задуматься неосновному потоку над задачей, а ввод с клавиатуры всё же оставить на главный поток?
D>По-моему у вас как-то всё наизнанку получается. Почему бы не дать задуматься неосновному потоку над задачей, а ввод с клавиатуры всё же оставить на главный поток?
Всё на самом деле так и построено- главный поток запускает поток вычислительный, с которым
засинхронизирован (потому что используют общие объекты VCL)
И из-за этой синхронизации главный не отвечает на клаву. Поэтому
я решил создать ещё один поток, в который перенаправить клавиатурный ввод главного потока
и там ловить нажатие ESC. Но, увы, всё не так просто оказалось...
Здравствуйте, Begemote, Вы писали:
B>Всё на самом деле так и построено- главный поток запускает поток вычислительный, с которым B>засинхронизирован (потому что используют общие объекты VCL) B>И из-за этой синхронизации главный не отвечает на клаву. Поэтому B>я решил создать ещё один поток, в который перенаправить клавиатурный ввод главного потока B>и там ловить нажатие ESC. Но, увы, всё не так просто оказалось...
Какой смысл тогда было делать дополнительный поток, если он замораживает основной? Постарайся делать меньше синхронизаций с основным потоком. Делай так, чтобы каждый занимался своим делом — главный с компонентами, а фоновый с каким-нибудь промежуточным хранилищем. Прячь компоненты, которые требуют долгого заполнения, чтобы они себя не перерисовывали итд.
D>>По-моему у вас как-то всё наизнанку получается. Почему бы не дать задуматься неосновному потоку над задачей, а ввод с клавиатуры всё же оставить на главный поток?
B>Всё на самом деле так и построено- главный поток запускает поток вычислительный, с которым B>засинхронизирован (потому что используют общие объекты VCL) B>И из-за этой синхронизации главный не отвечает на клаву. Поэтому B>я решил создать ещё один поток, в который перенаправить клавиатурный ввод главного потока B>и там ловить нажатие ESC. Но, увы, всё не так просто оказалось...
а вот тут поточнее...
именно так все и должно работать.
такая схема приводится в этом форуме если не раз в неделю, то раз в месяц точно! и она нормально всегда работает.
Здравствуйте, Dimonka, Вы писали:
D>Здравствуйте, Begemote, Вы писали:
D>Какой смысл тогда было делать дополнительный поток, если он замораживает основной? Постарайся делать меньше синхронизаций с основным потоком. Делай так, чтобы каждый занимался своим делом — главный с компонентами, а фоновый с каким-нибудь промежуточным хранилищем. Прячь компоненты, которые требуют долгого заполнения, чтобы они себя не перерисовывали итд.
Согласен, лучше конечно вообще без синхронизации. Но если уж так всё написано (и причем давно), и отчет там сложный очень —
короче, переделывать влом, то небольшая доработка ввиде ещё одного потока вроде бы не так трудоемка.
Но как победить эту проблему?
Здравствуйте, Oleg A. Bachin, Вы писали:
OAB>Здравствуйте, Begemote, Вы писали:
OAB>а вот тут поточнее... OAB>именно так все и должно работать.
OAB>такая схема приводится в этом форуме если не раз в неделю, то раз в месяц точно! и она нормально всегда работает.
Если поточнее, то примерно так (вернусь к самому началу):
procedure TBreakThread.Execute;
var
msg: TMsg;
begin
if not AttachThreadInput(MainThreadID,SecThreadId,true) then
exit;
while GetMessage(msg, 0, 0, 0) do begin
case msg.message of
WM_KEYDOWN : какое-то действие
end;
end;
end;
GetMessage ничего не возвращает !!!
OAB>>а вот тут поточнее... OAB>>именно так все и должно работать.
OAB>>такая схема приводится в этом форуме если не раз в неделю, то раз в месяц точно! и она нормально всегда работает.
B>Если поточнее, то примерно так (вернусь к самому началу):
вернись к тому варианту, когда визуалка и все тому подобное работает в главном потоке, а вычисления — в созданном тобой.
твой вариан не логичен по определению! ну сам подумай, вот тебе понабодится запустить 2 таких отчета! что ты будешь делать? создашь еще один главный поток?
Здравствуйте, Oleg A. Bachin, Вы писали:
OAB>Здравствуйте, Begemote, Вы писали:
OAB>>>а вот тут поточнее... OAB>>>именно так все и должно работать.
OAB>>>такая схема приводится в этом форуме если не раз в неделю, то раз в месяц точно! и она нормально всегда работает.
B>>Если поточнее, то примерно так (вернусь к самому началу):
OAB>вернись к тому варианту, когда визуалка и все тому подобное работает в главном потоке, а вычисления — в созданном тобой.
OAB>твой вариан не логичен по определению! ну сам подумай, вот тебе понабодится запустить 2 таких отчета! что ты будешь делать? создашь еще один главный поток?
Так у меня вся визуалка в главном потоке, вычисления делаются в другом потоке. Результаты вычислений сразу (без буферного хранилища)
попадают в VCL компоненты основного потока. Поэтому потоки засинхронизированы между собой и основной не отвечает сразу на события.
Так вот задача такая: НИЧЕГО не переделывая создать ещё один поток, который только и будет что ждать нажатия определенной клавиши.
Возможно ли это сделать с помощью AttachThreadInput и GetMessage?
Здравствуйте, Begemote, Вы писали:
B>Так у меня вся визуалка в главном потоке, вычисления делаются в другом потоке. Результаты вычислений сразу (без буферного хранилища) B>попадают в VCL компоненты основного потока. Поэтому потоки засинхронизированы между собой и основной не отвечает сразу на события. B>Так вот задача такая: НИЧЕГО не переделывая создать ещё один поток, который только и будет что ждать нажатия определенной клавиши. B>Возможно ли это сделать с помощью AttachThreadInput и GetMessage?
Может лучше иногда подталкивать проверку вместе с отрисовкой вызовом Application.ProcessMessages?
вот и будет тебе проверка в главном потоке. главный поток у тебя все это свободен же! я правильно понимаю?
Здравствуйте, Oleg A. Bachin, Вы писали:
OAB>Здравствуйте, Begemote, Вы писали:
B>>Так у меня вся визуалка в главном потоке, вычисления делаются в другом потоке. Результаты вычислений сразу (без буферного хранилища) B>>попадают в VCL компоненты основного потока. Поэтому потоки засинхронизированы между собой и основной не отвечает сразу на события. B>>Так вот задача такая: НИЧЕГО не переделывая создать ещё один поток, который только и будет что ждать нажатия определенной клавиши. B>>Возможно ли это сделать с помощью AttachThreadInput и GetMessage?
OAB>Может лучше иногда подталкивать проверку вместе с отрисовкой вызовом Application.ProcessMessages? OAB>вот и будет тебе проверка в главном потоке. главный поток у тебя все это свободен же! я правильно понимаю?
Да, правильно — основной поток ничегошеньки не делает, только рисует.
За Application.ProcessMessages спасибо, сейчас попробую, и думаю должно помочь. Неудобство только в том, что
вставить придется не один раз.
И всё же никак не могу понять, почему из очереди ввода основного потока, присоединенной к другому потоку
в этом (другом) потоке ничего недостается (в смысле никаких клавиатурных событий не вытаскивается) с помощью GetMessage? Вот когда напрямую отправляю сообщение этому потоку (PostThreadMessage), то GetMessage его возвращает. А на клаву не реагирует никак.
Хотя AttachThreadInput вроде как очередь присоединяет...