Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
8-5067
White1
2002-10-17 13:32
2003.02.03
Сохранить изображение как *.bmp файл


1-4843
avch
2003-01-24 15:18
2003.02.03
Как запустить/активизировать приложение


3-4713
ledzzz
2003-01-17 17:53
2003.02.03
штрихкод


3-4820
MAD-Sudarchikov
2003-01-17 17:27
2003.02.03
Компонент ListView и DBGrid


3-4816
Oleg__
2003-01-17 10:01
2003.02.03
Запрос из dll





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский