Проблема с TThread
От: Begemote  
Дата: 11.08.04 09:32
Оценка:
Помогите пож-та, решить такую проблему:
есть основной поток, т.е. создавший главное окно.
Он решает какую-то задачу и задумался надолго.
На клавиши, да и на другие события не реагирует.
Юзеру же необходима возможность отмены той задачи,
которой занимается основной поток (например, построение отчетов)
Он нажимает 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 не возвращает. Непонятно почему.
Re: Проблема с TThread
От: Dimonka Верблюд  
Дата: 11.08.04 09:41
Оценка:
Здравствуйте, Begemote, Вы писали:

B>Помогите пож-та, решить такую проблему:

B>есть основной поток, т.е. создавший главное окно.
B>Он решает какую-то задачу и задумался надолго.
B>На клавиши, да и на другие события не реагирует.
B>Юзеру же необходима возможность отмены той задачи,
B>которой занимается основной поток (например, построение отчетов)
B>Он нажимает ESC и хочет оменить всё.
B>Так вот я создаю 2-ой поток, присоединяю
B>очередь ввода основного потока к этому
B>и вхожу в цикл GetMessage. Насколько я понимаю,
B>все сообщения ввода клавиатурного теперь должны попасть в очередь
B>2-го потока и он уже отменит задачу.

По-моему у вас как-то всё наизнанку получается. Почему бы не дать задуматься неосновному потоку над задачей, а ввод с клавиатуры всё же оставить на главный поток?
Re[2]: Проблема с TThread
От: Begemote  
Дата: 11.08.04 09:48
Оценка:
Здравствуйте, Dimonka, Вы писали:


D>По-моему у вас как-то всё наизнанку получается. Почему бы не дать задуматься неосновному потоку над задачей, а ввод с клавиатуры всё же оставить на главный поток?


Всё на самом деле так и построено- главный поток запускает поток вычислительный, с которым
засинхронизирован (потому что используют общие объекты VCL)
И из-за этой синхронизации главный не отвечает на клаву. Поэтому
я решил создать ещё один поток, в который перенаправить клавиатурный ввод главного потока
и там ловить нажатие ESC. Но, увы, всё не так просто оказалось...
Re[3]: Проблема с TThread
От: Dimonka Верблюд  
Дата: 11.08.04 09:54
Оценка: +1
Здравствуйте, Begemote, Вы писали:

B>Всё на самом деле так и построено- главный поток запускает поток вычислительный, с которым

B>засинхронизирован (потому что используют общие объекты VCL)
B>И из-за этой синхронизации главный не отвечает на клаву. Поэтому
B>я решил создать ещё один поток, в который перенаправить клавиатурный ввод главного потока
B>и там ловить нажатие ESC. Но, увы, всё не так просто оказалось...

Какой смысл тогда было делать дополнительный поток, если он замораживает основной? Постарайся делать меньше синхронизаций с основным потоком. Делай так, чтобы каждый занимался своим делом — главный с компонентами, а фоновый с каким-нибудь промежуточным хранилищем. Прячь компоненты, которые требуют долгого заполнения, чтобы они себя не перерисовывали итд.
Re[3]: Проблема с TThread
От: Oleg A. Bachin Украина  
Дата: 11.08.04 09:58
Оценка:
Здравствуйте, Begemote, Вы писали:


D>>По-моему у вас как-то всё наизнанку получается. Почему бы не дать задуматься неосновному потоку над задачей, а ввод с клавиатуры всё же оставить на главный поток?


B>Всё на самом деле так и построено- главный поток запускает поток вычислительный, с которым

B>засинхронизирован (потому что используют общие объекты VCL)
B>И из-за этой синхронизации главный не отвечает на клаву. Поэтому
B>я решил создать ещё один поток, в который перенаправить клавиатурный ввод главного потока
B>и там ловить нажатие ESC. Но, увы, всё не так просто оказалось...

а вот тут поточнее...
именно так все и должно работать.

такая схема приводится в этом форуме если не раз в неделю, то раз в месяц точно! и она нормально всегда работает.
Best regards,
Oleg A. Bachin
Re[4]: Проблема с TThread
От: Begemote  
Дата: 11.08.04 10:00
Оценка:
Здравствуйте, Dimonka, Вы писали:

D>Здравствуйте, Begemote, Вы писали:



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


Согласен, лучше конечно вообще без синхронизации. Но если уж так всё написано (и причем давно), и отчет там сложный очень —
короче, переделывать влом, то небольшая доработка ввиде ещё одного потока вроде бы не так трудоемка.
Но как победить эту проблему?
Re[4]: Проблема с TThread
От: Begemote  
Дата: 11.08.04 10:04
Оценка:
Здравствуйте, 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 ничего не возвращает !!!
Re[5]: Проблема с TThread
От: Oleg A. Bachin Украина  
Дата: 11.08.04 11:19
Оценка:
Здравствуйте, Begemote, Вы писали:


OAB>>а вот тут поточнее...

OAB>>именно так все и должно работать.

OAB>>такая схема приводится в этом форуме если не раз в неделю, то раз в месяц точно! и она нормально всегда работает.


B>Если поточнее, то примерно так (вернусь к самому началу):


вернись к тому варианту, когда визуалка и все тому подобное работает в главном потоке, а вычисления — в созданном тобой.

твой вариан не логичен по определению! ну сам подумай, вот тебе понабодится запустить 2 таких отчета! что ты будешь делать? создашь еще один главный поток?
Best regards,
Oleg A. Bachin
Re[6]: Проблема с TThread
От: Begemote  
Дата: 12.08.04 08:40
Оценка:
Здравствуйте, Oleg A. Bachin, Вы писали:

OAB>Здравствуйте, Begemote, Вы писали:



OAB>>>а вот тут поточнее...

OAB>>>именно так все и должно работать.

OAB>>>такая схема приводится в этом форуме если не раз в неделю, то раз в месяц точно! и она нормально всегда работает.


B>>Если поточнее, то примерно так (вернусь к самому началу):


OAB>вернись к тому варианту, когда визуалка и все тому подобное работает в главном потоке, а вычисления — в созданном тобой.


OAB>твой вариан не логичен по определению! ну сам подумай, вот тебе понабодится запустить 2 таких отчета! что ты будешь делать? создашь еще один главный поток?


Так у меня вся визуалка в главном потоке, вычисления делаются в другом потоке. Результаты вычислений сразу (без буферного хранилища)
попадают в VCL компоненты основного потока. Поэтому потоки засинхронизированы между собой и основной не отвечает сразу на события.
Так вот задача такая: НИЧЕГО не переделывая создать ещё один поток, который только и будет что ждать нажатия определенной клавиши.
Возможно ли это сделать с помощью AttachThreadInput и GetMessage?
Re[7]: Проблема с TThread
От: Oleg A. Bachin Украина  
Дата: 12.08.04 08:46
Оценка:
Здравствуйте, Begemote, Вы писали:

B>Так у меня вся визуалка в главном потоке, вычисления делаются в другом потоке. Результаты вычислений сразу (без буферного хранилища)

B>попадают в VCL компоненты основного потока. Поэтому потоки засинхронизированы между собой и основной не отвечает сразу на события.
B>Так вот задача такая: НИЧЕГО не переделывая создать ещё один поток, который только и будет что ждать нажатия определенной клавиши.
B>Возможно ли это сделать с помощью AttachThreadInput и GetMessage?

Может лучше иногда подталкивать проверку вместе с отрисовкой вызовом Application.ProcessMessages?
вот и будет тебе проверка в главном потоке. главный поток у тебя все это свободен же! я правильно понимаю?
Best regards,
Oleg A. Bachin
Re[8]: Проблема с TThread
От: Begemote  
Дата: 12.08.04 09:07
Оценка:
Здравствуйте, Oleg A. Bachin, Вы писали:

OAB>Здравствуйте, Begemote, Вы писали:


B>>Так у меня вся визуалка в главном потоке, вычисления делаются в другом потоке. Результаты вычислений сразу (без буферного хранилища)

B>>попадают в VCL компоненты основного потока. Поэтому потоки засинхронизированы между собой и основной не отвечает сразу на события.
B>>Так вот задача такая: НИЧЕГО не переделывая создать ещё один поток, который только и будет что ждать нажатия определенной клавиши.
B>>Возможно ли это сделать с помощью AttachThreadInput и GetMessage?

OAB>Может лучше иногда подталкивать проверку вместе с отрисовкой вызовом Application.ProcessMessages?

OAB>вот и будет тебе проверка в главном потоке. главный поток у тебя все это свободен же! я правильно понимаю?

Да, правильно — основной поток ничегошеньки не делает, только рисует.
За Application.ProcessMessages спасибо, сейчас попробую, и думаю должно помочь. Неудобство только в том, что
вставить придется не один раз.
И всё же никак не могу понять, почему из очереди ввода основного потока, присоединенной к другому потоку
в этом (другом) потоке ничего недостается (в смысле никаких клавиатурных событий не вытаскивается) с помощью GetMessage? Вот когда напрямую отправляю сообщение этому потоку (PostThreadMessage), то GetMessage его возвращает. А на клаву не реагирует никак.
Хотя AttachThreadInput вроде как очередь присоединяет...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.