Форум: "Основная";
Текущий архив: 2003.02.03;
Скачать: [xml.tar.bz2];
ВнизОкошко в отдельном потоке. Как? Найти похожие ветки
← →
tga (2003-01-23 12:09) [0]У меня возникла трабла с открытием окна в отдельном потоке программы. Окно создаю вот так:
var
dialog:TForm;
...
dialog := CreateMessageDialog("...",mtConfirmation , [mbYes, mbYesToAll, mbNoToAll, mbNo]);
Если разделение на потоки не делать - то всё работает. А вот в отдельном потоке говорит следующее:
... rised exception class EInvalidOperation with message "Canvas does not allow drawing".
Подскажите как от этой ошибки избавиться.
P/S Работаю на D6 под WinXP
← →
Reindeer Moss Eater (2003-01-23 12:15) [1]Объекты пользовательского интерфейса должны жить в главном потоке процеса.
← →
tga (2003-01-23 12:18) [2]Странный ответ.... как это так должны ?
Ты не обижайся - но такого долженствования никто в парадигмы параллельного программирования не ставил... в том чисе и для D6.
← →
Reindeer Moss Eater (2003-01-23 12:24) [3]Ответ странный для тех, кто не заглядывал в руководство. В том числе и по D6.
← →
Digitman (2003-01-23 12:26) [4]
> как это так должны?
А вот так !
Пользовательский интерфейс требует как минимум GDI-ресурсы системы
GDI-ресурсы - неразделяемые, запрос/обращение/освобождение их должно осуществляться в осн.код.потоке процесса
В VCL это делается через методы/св-ва объектов, скрыто работающих с этими ресурсами
Отсюда вывод : обращайся к методам/св-вам таких объектов ТОЛЬКО в осн.код.потоке
Таким объектом в дан.случае явл-ся MessageDialog, ты создаешь и пользуешь его не в осн., а в доп.потоке, вот тебе и "грабли")
Синхронизируй вызов CreateMessageDialog() с сообщениями окна осн.потока. См. TThread.Synchronize()
← →
MBo (2003-01-23 12:27) [5]>но такого долженствования никто в парадигмы параллельного программирования не ставил...
Microsoft ставил...
← →
tga (2003-01-23 12:34) [6]Ух мужики!!!
вот так уже понятней :))
Я проблему немного подругому решил -
1 перед запуском потока создаю окошко и ссылочку запоминаю
2 в потоке его показываю
3 по завершении поток - грохаю окно...
работает, только вот "отображение" этого окна (исходяиз того что сказал Digitman ) нужно так-же синхронизировать, а вот с чем его синхронизировать я пока понять не могу...
← →
Digitman (2003-01-23 12:37) [7]см. > MBo © (23.01.03 12:27)
И не мог не поставить. Потому как басню "лебедь, рак и щука" наверняка читал.
Лебедь- 1-й поток процесса
Рак - 2-й поток процесса
Щука - 3-й поток процесса
Каждый из потоков параллельно (!), согласно твоей "парадигме" пытается тащить "воз" в свою сторону : один хочет нарисовать точку с координатами (0,0), другой - стереть, третий цвет изменить. И все это - одновременно !?
Вот MS и сказал разработчикам : буду исполнять такие команды последовательно для каждого процесса, а слушать буду только команды осн.потока каждого процесса. Кто не подчинится - хрен тому, а не "воз"))))
← →
tga (2003-01-23 12:44) [8]ага...
т.е. достаточно создавать объекты интерфейса в главном потоке, а их использование (вызов методов) исполнять через TThread.Synchronize() и всё должно работать , так? :)))
по хелпу похоже что так... :))
← →
Digitman (2003-01-23 13:06) [9]лучше вообще отказаться от непосредственной работы с объектами интерфейса в доп.код.потоке.
это не его задача.
задача доп.код.потока - выполнять "тяжелые", длительные циклические вычисления, которые в случае выполнения в осн.код.потоке блокируют обработку очереди сообщений окнам осн.потока до момента завершения вычислений
← →
vuk (2003-01-23 14:37) [10]to DigitmanL
>GDI-ресурсы - неразделяемые, запрос/обращение/освобождение их
>должно осуществляться в осн.код.потоке процесса
Не совсем так. Ограничение на работу с интерфейсом в одном потоке - это ограничение VCL, а не Windows. Если создать средствами WinAPI окно в отдельном потоке и расписать там же цикл обработки сообщений, то все замечательно будет жить.
← →
Digitman (2003-01-23 15:20) [11]
> vuk
Мало ли какие ограничения в VCL ! Я не о них. Это само собой разумеется.
Ты хочешь сказать, что если в обработчиках оконных сообщений в двух или более код.потоках будет одновременно выполнена, скажем, та же SetTextColor() с одним и тем же hDC, то - никаких проблем ? И Win32 сериализует вызовы, непосредственно модифирующие поверхность ??
Убеди меня в этом.
← →
vuk (2003-01-23 15:31) [12]Я немного не про то, похоже не совсем то процитировал, что нужно. Моя вина.
Вы совершенно правы, DC окна для той же отрисовки существует только на период отработки WM_PAINT, а оно отрабатывается только в том потоке, который создал окно.
Возражать же мне следовало против этого:
>Вот MS и сказал разработчикам : буду исполнять такие команды
>последовательно для каждого процесса, а слушать буду только
>команды осн.потока каждого процесса.
← →
Digitman (2003-01-23 15:54) [13]а что, по-твоему, здесь явно противоречит истине ?
← →
vuk (2003-01-23 16:02) [14]>а что, по-твоему, здесь явно противоречит истине ?
Истине противоречит то, что окно (не VCL) в отдельном потоке жить может. Зуб даю. :o)
← →
Digitman (2003-01-23 16:20) [15]конечно, может) ... я и не отрицаю.
Любой код.поток может собственное создать окно и получать адресованные этому окну сообщения.
но я - не об окнах как приемниках сообщений ! а об окнах, с которыми ассоциированы неразделяемые GDI-ресурсы
← →
vuk (2003-01-23 16:22) [16]>а об окнах, с которыми ассоциированы неразделяемые GDI-ресурсы
Хотите сказать, что я в отдельном потоке WM_PAINT не отработаю? :o)
← →
Digitman (2003-01-23 16:31) [17]смотря что в обработчике WM_PAINT ты делать будешь)
← →
vuk (2003-01-23 16:33) [18]>смотря что в обработчике WM_PAINT ты делать будешь
Рисовать, понятное дело. На DC.
← →
Digitman (2003-01-23 16:50) [19]вот и попробуй создать VCL-форму в доп.потоке (чем не окно ?), организовать цикл приема и диспетчеризации сообщений ("рисующие" обработчики сообщений уже есть в объекте-форме) и тут же установить св-во Visible=True )
Чем такая схема отличается от организации того же средствами WinAPI ? Ничем. Окно индивидуально для потока, ни один другой поток не обращается к форме. Однако, "canvas does not allow drawing", надеюсь, ты увидишь)
← →
vuk (2003-01-23 17:13) [20]>вот и попробуй создать VCL-форму
Я ж сказал - не VCL. VCL окно создать не получится по той причине, что внутри будут обращения к глобальным объектам типа Application.
А вот на WinAPI - одной левой. Я ж сказал - зуб даю. :o)
unit Unit2;
interface
uses
Windows,
Messages,
sysutils,
Classes;
type
TWndThread = class(TThread)
procedure Execute; override;
end;
implementation
{ TWndThread }
function WindowProc(hWnd: THandle; uMsg, wParam, lParam: Integer): Integer;
stdcall;
procedure HandleWMPaint;
var
DC : HDC;
PS : TPaintStruct;
s : string;
begin
DC := BeginPaint(hWnd, PS );
Ellipse(DC, 0, 0, 100, 50);
s := FormatDateTime("hh:nn:ss", Now);
TextOut(DC, 20, 15, PChar(s), length(s) );
EndPaint(hWnd, PS);
end;
begin
Result := 0;
case uMsg of
WM_DESTROY:
PostQuitMessage(0);
WM_PAINT: HandleWMPaint;
WM_TIMER: RedrawWindow(hWND, nil, 0, RDW_INVALIDATE);
end;
Result := DefWindowProc(hWnd, uMsg, wParam, lParam);
end;
procedure TWndThread.Execute;
var
hWnd: THandle;
WndClass: TWndClass;
Msg: TMsg;
const
sClassName = "MyWND";
begin
FillChar(WndClass, SizeOf(WndClass), 0);
with WndClass do
begin
hInstance := hInstance;
lpszClassName := sClassName;
lpfnWndProc := @WindowProc;
hbrBackground := GetStockObject(LTGRAY_BRUSH);
end;
Windows.RegisterClass(WndClass);
hWnd := CreateWindow(sClassName, "", WS_OVERLAPPEDWINDOW, 200, 200, 300, 300, 0, 0, hInstance, nil);
if hWnd = 0 then
Exit;
ShowWindow(hWnd, SW_normal);
UpdateWindow(HWND);
//таймер будет имитировать бурную деятельность
SetTimer(HWND, 1, 1000, nil );
while GetMessage(Msg, 0, 0, 0) do
begin
if msg.message = WM_QUIT then
break;
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
KillTimer(HWND, 1);
end;
end.
← →
Бурундук (2003-01-23 17:28) [21]2Digitman © (23.01.03 16:50)
Пробовал (даже в VCL) - но "canvas does not allow drawing" не видел.
В VCL единственно вполне могут быть проблемы с глобальными объектами Application и Screen, в коде которых нет никаких
намёков на возможность использования их в нескольких потоках.
А вот все VCLные гди-манаджеры (FontManager etc), напротив,
выглядят вроде бы (с первого взгляда) вполне потокобезопасно -
все операции защищены критической секцией.
(Кстати, у Рихтера где-то было написано, что при
создании окна с родительским окном в другом потоке
автоматически вызывается AttachThreadInput -
отсюда по крайней мере следует, что возможность
создания окон в разных потоках в принципе
в чистом WinApi допускается).
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.02.03;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.01 c