Текущий архив: 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.5 MB
Время: 0.015 c