![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Заставить Application.ProcessMessages работать в чужом потоке
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), а дополнительный своим (длительные вычисления в контексте строго определенной возложенной на поток задачи)