Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.02.03;
Скачать: CL | DM;

Вниз

Окошко в отдельном потоке. Как?   Найти похожие ветки 

 
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;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.012 c
1-4980
Прога
2003-01-23 10:58
2003.02.03
Управление MathCAD


3-4735
ufff
2003-01-13 17:14
2003.02.03
for select


4-5340
Vuture
2002-12-20 14:46
2003.02.03
Как залочить диск (например флоппик)?


1-5038
nikulin
2003-01-24 09:58
2003.02.03
Где найти?


1-4991
xn0bys
2003-01-23 11:31
2003.02.03
Обработка Ошибки Загрузки Файла