Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2005.12.18;
Скачать: [xml.tar.bz2];

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.012 c
14-1133159149
Ega23
2005-11-28 09:25
2005.12.18
С днем рождения! 27 ноября


14-1132901183
Ega23
2005-11-25 09:46
2005.12.18
С днем рождения! 25 ноября


3-1130837150
Punch
2005-11-01 12:25
2005.12.18
Индекс на поле.


4-1129480611
FunkyByte
2005-10-16 20:36
2005.12.18
Как получить путь к папке "Мои документы"?


1-1132889105
beglec
2005-11-25 06:25
2005.12.18
Как загрузить банер в программу?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский