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

Вниз

CheckBox.Checked и многопоточность.   Найти похожие ветки 

 
jolik ©   (2005-11-24 18:48) [0]

Как думает All - можно ли проверять CheckBox.Checked в неосновной нитке программы? Вернее - проверять то можно, только вот не приведет ли это в конце концов к фатальным последствиям, ведь обращаться к визуальным компонентам можно только из основного потока программы.
В исходниках проверяется так:

function TCustomCheckBox.GetChecked: Boolean;
begin
 Result := State = cbChecked;
end;

т.е. вроде ничего нереентерабельного нет - но, может есть еще какие соображения.
Заранее благодарен!


 
TUser ©   (2005-11-24 18:54) [1]


> обращаться к визуальным компонентам можно только из основного
> потока программы.

TThread.Synchronize


 
GuAV ©   (2005-11-24 18:55) [2]

Смотрим далее
   FState: TCheckBoxState;
 TCheckBoxState = (cbUnchecked, cbChecked, cbGrayed);

т.е. сравнение поля Enumeration с константой. Получение Enumeraion потокобезопасно. Т.е. если он сущесвует, всё ок.

ЗЫ:
Но я бы не стал так делать, а сделал бы так: при изменении Checked обработчиком основного потока меняется флаг в дополнительном.


 
Jolik ©   (2005-11-25 00:35) [3]


> ЗЫ:
> Но я бы не стал так делать, а сделал бы так: при изменении
> Checked обработчиком основного потока меняется флаг в дополнительном.
>

Так и делаю...
Просто задумался - фактически читается integer - а это атомарная операция. другое дело в другой версии дельфе неизвестно че будет.
Спасибо!


 
Eraser ©   (2005-11-25 00:51) [4]


> Jolik ©   (25.11.05 00:35) [3]


>  фактически читается integer - а это атомарная операция

Это с какого перепугу?

Вся фишка в том, что когда вызываешь TCustomCheckBox.GetChecked происходит + ко всему обращение к DC этого CustomCheckBox"a, что из другого потока - не безопасно.


 
Leonid Troyanovsky ©   (2005-11-25 10:21) [5]


> Jolik ©   (25.11.05 00:35) [3]

> Так и делаю...


Лучше SendMessage (Chb.Handle, BM_GETCHECK, 0, 0)

Обращаться к Checked напрямую не следует хотя бы потому,
что безопасная в настоящем функция может быть замещена другой,
например,  с побочными визуальными эффектами.

--
Regards, LVT.


 
GuAV ©   (2005-11-25 12:00) [6]

Eraser ©   (25.11.05 0:51) [4]

> ко всему обращение к DC этого CustomCheckBox"a, что из
> другого потока - не безопасно.

С чего бы это
   property State: TCheckBoxState read FState write SetState default cbUnchecked;
  FState: TCheckBoxState;
TCheckBoxState = (cbUnchecked, cbChecked, cbGrayed);

Функция GetChecked к DC  не обращается.

Leonid Troyanovsky ©   (25.11.05 10:21) [5]

> Лучше SendMessage (Chb.Handle, BM_GETCHECK, 0, 0)

Уже вроде обсуждалось, получение хедла не потокобезопасно.


 
Leonid Troyanovsky ©   (2005-11-25 13:35) [7]


> GuAV ©   (25.11.05 12:00) [6]

> > Лучше SendMessage (Chb.Handle, BM_GETCHECK, 0, 0)

> Уже вроде обсуждалось, получение хедла не потокобезопасно.


Где обсуждалось? Можно просто резюме.
Впрочем, пусть будет ChbHandle.

--
Regards, LVT.


 
GuAV ©   (2005-11-25 15:21) [8]


> Можно просто резюме.

Просто резюме:

Хендлы контролов могут быть пересозданны при изменении свойств. Поэтому при всех использования хендлов в других потоках следует проверять, изменяются ли такие свойства в основном. Можно (1) просмотреть исходники контрола для меняемых в основном потоке св-в и убедится, что хендл не пересоздаётся (2) отказаться от изменения любых св-в в основном потоке (3) синхронизировать изменение св-ва.


> Впрочем, пусть будет ChbHandle.

Не лучше, всвязи с вышеизложенным.


 
Leonid Troyanovsky ©   (2005-11-25 15:43) [9]


> GuAV ©   (25.11.05 15:21) [8]

> > Впрочем, пусть будет ChbHandle.
> Не лучше, всвязи с вышеизложенным.


 Почему ж не лучше? Потокобезопасней ;)

Хотя, и в резюме есть некоторые натяжки.
Бо, получим мы всегда хендл, просто не всегда он будет валиден.
Т.е., будут существовать моменты, когда он будет относится
к старому окну.

--
Regards, LVT.


 
GuAV ©   (2005-11-25 17:20) [10]


>  Почему ж не лучше? Потокобезопасней ;)

Угу ;) не-потокобезопасен не метод получения, а значение


> просто не всегда он будет валиден.

Более того, виндовс может создать новое окно с тем же хендлом.


 
Eraser ©   (2005-11-25 17:28) [11]


> Eraser ©   (25.11.05 00:51) [4]

Да, тут я не совсем точен, т.к. Leonid Troyanovsky ©   (25.11.05 10:21) [5], а по-умолчанию прорисовка осуществляется по сообщению и в главном потоке.
procedure TCustomCheckBox.SetState(Value: TCheckBoxState);
begin
 if FState <> Value then
 begin
   FState := Value;
   if HandleAllocated then
     SendMessage(Handle, BM_SETCHECK, Integer(FState), 0);
   if not ClicksDisabled then Click;
 end;
end;


> GuAV ©   (25.11.05 17:20) [10]


> Более того, виндовс может создать новое окно с тем же хендлом.

А это ещё почему?


 
GuAV ©   (2005-11-25 17:43) [12]


> А это ещё почему?

А если старого окна уже нет, то почему бы и нет ?


 
Leonid Troyanovsky ©   (2005-11-25 17:49) [13]


> GuAV ©   (25.11.05 17:20) [10]

> Угу ;) не-потокобезопасен не метод получения, а значение

Да ничего особо страшного не произойдет при посылке уже
не существуещему окну. Ну, вернется 0, далее поток должен
что-то предпринимать.

Другое дело, если контрол к тому времени будет разрушен.
Но, это уже другой вопрос ;)

> Более того, виндовс может создать новое окно с тем же хендлом.

 В обычной жизни (т.е., вне пограничных состояний) такого не случится.
 Неохота искать, но, когда-то, в microsoft.public.win32.programmer.kernel
 обсуждался механизм присвоения хендлов окнам, в вопросе типа,
 уникално ли значение хендла окна в сессии.

--
Regards, LVT.


 
Eraser ©   (2005-11-25 17:54) [14]


> GuAV ©   (25.11.05 17:43) [12]

А, всё понял ЧТО имеется ввиду, вначале подумал, что виндовз создаст хендл который уже существует... не важно короче... )

только вот не пойму в чём опасность пересоздания дескриптора.
При вызове SendMessage (Chb.Handle, BM_GETCHECK, 0, 0)
бедет вызван метод
function TWinControl.GetHandle: HWnd;
begin
 HandleNeeded;
 Result := FHandle;
end;

который скорее всего успешно вызовет
procedure TWinControl.HandleNeeded;
begin
 if FHandle = 0 then
 begin
   if Parent <> nil then Parent.HandleNeeded;
   CreateHandle;
 end;
end;


и возвратит действительный дескриптор.


 
Leonid Troyanovsky ©   (2005-11-25 18:20) [15]


> Eraser ©   (25.11.05 17:54) [14]

> который скорее всего успешно вызовет


Он всегда вызовет успешно. Но без гарантии, что это значение новое.
И особенно в случае многопроцессорной машины.

--
Regards, LVT.


 
Eraser ©   (2005-11-25 18:27) [16]


> Leonid Troyanovsky ©   (25.11.05 18:20) [15]

И то верно, никакой гарантии что поток не "прервётся" посреди HandleNeeded и в этот момент другой поток её вызовет нету, но всё таки у данного подхода очень высокая надёжность... imho..., в крайнем случае можно и через synchronize... )


 
Leonid Troyanovsky ©   (2005-11-25 18:28) [17]


> Leonid Troyanovsky ©   (25.11.05 18:20) [15]

> > который скорее всего успешно вызовет


А в случае FHandle = 0 создаст еще окно в своем потоке :)

--
Regards, LVT


 
Leonid Troyanovsky ©   (2005-11-25 18:43) [18]


> Eraser ©   (25.11.05 18:27) [16]

> И то верно, никакой гарантии что поток не "прервётся" посреди
> HandleNeeded и в этот момент другой поток её вызовет нету,
>  но всё таки у данного подхода очень высокая надёжность.
> .. imho..., в крайнем случае можно и через synchronize..



До крайности можно и не доходить ;)
Просто решение использовать CheckBox для синхронизации должно
быть подкреплено некими действиями по безопасности.
Т.е., при совершении с этим боксом неких действий, могущих привести
к RecreateWnd или, скажем, к разрушению бокса, нужно перво-наперво
этот поток прибить, что собс-но, вполне логично.

--
Regards, LVT.


 
Eraser ©   (2005-11-25 19:20) [19]


> Leonid Troyanovsky ©   (25.11.05 18:43) [18]


>  нужно перво-наперво
> этот поток прибить

ну зачем же так грубо?
можно просто suspend, а потом resume
:-)



Страницы: 1 вся ветка

Текущий архив: 2005.12.18;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.045 c
3-1131003784
gusev
2005-11-03 10:43
2005.12.18
Ошибка в запросе по дате и времени


14-1132758402
lookin
2005-11-23 18:06
2005.12.18
Локаут и повседневность. USA vs Россия.


14-1133048630
Fl@sh
2005-11-27 02:43
2005.12.18
PIC контроллеры + литература


14-1133210265
DillerXX
2005-11-28 23:37
2005.12.18
far


4-1129271146
Roughneck
2005-10-14 10:25
2005.12.18
CreateProcessAsUser или CreateProcessWithLogonW