Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Заставить Application.ProcessMessages работать в чужом потоке


Страницы:   1 2

DelphiLexx ©   (2008-10-31 15:15:00) 

Как мы знаем вызов Application.ProcessMessages приводит к тому что происходит обработка очереди сообщений того потока в котором собственно вызывался. У меня вопрос как в Delphi можно заставить подобную ф-цию произвести обработку сообщения в контексте заданного потока т.е. как то так:

Application.ProcessMessages(dwThreadID: DWORD);

Нужно мне собственно для того, чтобы можно было выполнить такую вещь:
MainThread (главный поток) cоздает ChildThread(дочерний поток), и далее MainThread начинает выполнять долгую операцию.

ChildThread(дочерний поток) - это по сути у меня окно в котором показывается время выполнения действия + какая-нить красивая анимация + ProgressBar и т.п. Это окно у меня используется во многих местах программы с разными MainThread'ами
так вот чтобы у пользователя не было ощущения что прога повисла делаем Application.ProcessMessages т.е.
-----------------------memory MainThread1----------------------
код инициализирующий ChildThread т.е. создание красивого окна ожидания ShowWinWait в отдельном потоке
какой код выполняющий в цикле сложные операции
for i := .. to .. do
Application.ProcessMessages
-----------------------------------------------------------------------

-----------------------memory MainThread2----------------------
код инициализирующий ChildThread т.е. создание красивого окна ожидания ShowWinWait в отдельном потокекакой код выполняющий сложные операции
Application.ProcessMessages
-----------------------------------------------------------------------

-----------------------memory MainThread3----------------------
код инициализирующий ChildThread т.е. создание красивого окна ожидания ShowWinWait в отдельном потокекакой код выполняющий сложные операции
Application.ProcessMessages
-----------------------------------------------------------------------

Как вы заметели приходиться в MainThread'ах вызывать Application.ProcessMessage это не очень удобно проще было бы так
-----------------------memory MainThread1----------------------
код инициализирующий ChildThread т.е. создание красивого окна ожидания с параметрами ShowWinWait(MainTID),
где MainTID = GetWindowThreadProcessId (Self.Handle, lpdwProcessId) - id MainThread1
какой код выполняющий в цикле сложные операции
for i := .. to .. do
-----------------------------------------------------------------------

------------------------memory ChildThread----------------------
здесь собственно код отображающие ProgressBar и т.д.
procedure OnTimerTime
begn
....
Application.ProcessMessages(MainTID);
end;
------------------------------------------------------------------------


Дмитрий Белькевич   (2008-11-05 15:03:00) [1]

Вот откопал:



program Project2;

{$R 'resources.RES'}

uses
SysUtils,
Windows,
Messages;

function WndFunc(Wnd, Msg: DWord; wParam, lParam: integer): integer; stdcall;
begin
   Result := 0
end;

begin { main }
DialogBox(hInstance,MAKEINTRESOURCE(10),0,@WndFunc);
// CreateDialog(hInstance,MAKEINTRESOURCE(10),0,@WndFunc);
end.



resources.rc, собирается brcc


/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
10 DIALOGEX 0, 0, 193, 74
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE |
 WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_TOPMOST
CAPTION "Test Application"
FONT 8, "Helv", 0, 0
BEGIN
 PUSHBUTTON      "Close",IDCANCEL,134,38,52,15
 LTEXT           "Test:",IDC_STATIC,7,7,107,10
 CONTROL         101,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,7,68,
                 179,3
 EDITTEXT        160,7,17,179,15,ES_AUTOHSCROLL | ES_READONLY
END


Но это так - наброски. Создавай такое окно (поправив предварительно ресурс), в отдельном потоке, обрабатывай сообщения от окна в WndFunc, позицию прогрессбара меняй из основного потока. Если нужен останов - обрабатывай нажатие контрола, выставляя какой-нибудь флаг в потоке.


Дмитрий Белькевич   (2008-11-05 14:33:00) [2]

Если я верно понял, то у тебя проблема, похожая на мою.

Основная проблема: "VCL - это однопотоковая библиотека. Это значит, что создавать и работать с формами вы можете только в главном потоке."

Я как-то занимался проблемой, но так окончательно и не доделал - пока ограничился костылями в некоторых местах, Application.Processmessage вызываю, хотя это у меня не всегда допустимо. Сдеалал флаги, что процедура еще не окончилась. Но это всё не важно.

Важно то, что в дополнительном потоке можно создать не форму делфи, но обычное окно windows. Проще всего, что бы не возиться с апи, сделать с помощью CreateDialog. Обрабатывать события по айдишникам контролов, если есть необходимость. Поищи тред обсуждения по моей фамилии.


DelphiLexx   (2008-11-05 10:16:00) [3]


> Synchronize(CallProcessMessages);

Под TMyThread понимается главный поток?


MetalFan   (2008-11-01 14:51:00) [4]

ага, но если главный поток загружен, то толку от этого не будет....


Leonid Troyanovsky   (2008-11-01 13:26:00) [5]


> DelphiLexx   (31.10.08 17:22) [13]

> Не понял, напримере не мог бы


procedure TMyThread.CallProcessMessages;
begin
 Application.ProcessMessages;
end;


> анимацией и прочей фигней, в нее же мне надо разместить
> ф-цию типа Application.ProcessMessages(MainThreadID) для
> обновления

Synchronize(CallProcessMessages);

--
Regards, LVT.


MetalFan   (2008-11-01 12:51:00) [6]


> На Исходниках тоже автора никто не понимает

да и на винграде тоже)


Сергей М.   (2008-11-01 10:12:00) [7]


> DelphiLexx


Если уж так приспичило напрячь осн.поток несвойственной ему работой, поступи след.образом:

1. Выкинь из проекта TimerThread - его существование бессмысленно и бесполезно

2. Вместо доп.потоков TimerThread и WinThread организуй единый доп.поток ProgressWinThread, в его контексте создаешь окно (именно окно, создаваемое непосредственным вызовом соотв.ф-ции в составе WinAPI-, а не VCL-форму !!!) и тут жеорганизуешь цикл ожидания/выборки/диспетчеризации сообщений. В этом окне в контексте этого жепотока рисуешь все что тебе нужно показать юзеру. Никаких таймеров при этом организовывать не нужно - небходимые временные выдержки обеспечиваются WaitForXXXX-функциями в составе WinAPI.


Германн   (2008-10-31 19:24:00) [8]


> И вопрос, как видно, как раз и заключается в

На Исходниках тоже автора никто не понимает
http://forum.sources.ru/index.php?showtopic=254918


Сергей М.   (2008-10-31 19:17:00) [9]


> Leonid Troyanovsky ©   (31.10.08 17:10) [12]


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

И вопрос, как видно, как раз и заключается в том как заставитьосн.поток прекратить на время заниматься этим черт-те чем и обработать очередь сообщений по кр.мере своим окнам ..


DelphiLexx   (2008-10-31 17:22:00) [10]


> Пользуй Synchronize метода потока, который и
> вызовет Application.ProcessMessages.

Не понял, напримере не мог бы


Leonid Troyanovsky   (2008-10-31 17:10:00) [11]


> DelphiLexx   (31.10.08 16:12) [8]

> в отдельном потоке (TimerThread) и  генерит событие OnTimer
> на это событие повешена ф-ция, которая управляет ProgressBar'ом
> анимацией и прочей фигней, в нее же мне надо разместить
> ф-цию типа Application.ProcessMessages(MainThreadID) для обновления
> очереди события главного потока

Пользуй Synchronize метода потока, который и
вызовет Application.ProcessMessages.
Ну, или пошли форме SendMessage, при обработке которого
она и вызовет Application.ProcessMessages.

--
Regards, LVT.


Сергей М.   (2008-10-31 16:52:00) [12]

Что мешает вынести создание окна в доп.поток, тот самый который у тебя шурудит таймером ?


DelphiLexx   (2008-10-31 16:41:00) [13]

Да


Сергей М.   (2008-10-31 16:20:00) [14]


> DelphiLexx   (31.10.08 16:12) [8]


Т.е. окно, в котором должно происходить все это чудодейство с прогресс-баром и анимацией, создано в контексте основногопотока, так ?


DelphiLexx   (2008-10-31 16:12:00) [15]


> Что сие означает ?

MainThread  - собственно главный поток.
WinWait - окно в котором отображается ProgressBar + анимация и т.п, данное окно содержит JVCL Timer который работает в отдельном потоке (TimerThread) и  генерит событие OnTimer на это событие повешена ф-ция, которая управляет ProgressBar'ом анимацией и прочей фигней, в нее же мне надо разместить ф-цию типа Application.ProcessMessages(MainThreadID) для обновления очереди события главного потока, если же я там размещу просто Application.ProcessMessages, то будет производиться обработка очереди сообщений потока TimerThread, но т.к. TimerThread - не содержит окон то это очередь всегда пуста и поэтому Application.ProcessMessages по сути ничего не выполняет полезного в данном случае.


KSergey   (2008-10-31 16:01:00) [16]

> KSergey ©   (31.10.08 16:01) [6]
> Винда сама ее красиво отрисует в другом (своем) потоке.

с.м. коирование файлов в проводнике, к примеру.


KSergey   (2008-10-31 16:01:00) [17]

Надо просто AVI-анимашку нарисовать - и все.
Винда сама ее красиво отрисует в другом (своем) потоке.


Сергей М.   (2008-10-31 15:52:00) [18]

Ну хорошо, надо так надо.


> ChildThread(дочерний поток) - это по сути у меня окно


Что сие означает ?


DelphiLexx   (2008-10-31 15:47:00) [19]


> Заставить кого-то делать что-то, чего он делать не умеет
> и/или не желает - это попахивает насилием)

есть условия не мною поставленные, необходимо их решить
вот я пытаюсь их решить


Сергей М.   (2008-10-31 15:34:00) [20]


> DelphiLexx   (31.10.08 15:15)  


Заставить кого-то делать что-то, чего он делать не умеет и/или не желает - это попахивает насилием)

А насиловать-то как раз никого не нужно, достаточно просто поставить все задуманное с головы на ноги: основной поток занимается своим делом (GUI), а дополнительный своим (длительные вычисления в контексте строго определенной возложенной на поток задачи)


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо