У разных объектов есть разные правила привязки к потокам - но базовые принципы пришли ещё из времён 16-ти битных Windows.
Самым важным элементом пользовательского интерфейса в Windows является, конечно же, окно. Объекты окон имеют привязку к создавшему их потоку. Поток, который создал окно, получает неразрываемую связь с окном. Говоря неформально: поток "владеет" окном. Сообщения отправляются в оконную процедуру только потоку владельцу, и, вообще говоря, модификации этого окна следует проводить только из потока, который создал окно. Хотя оконный менеджер допускает доступ к окну (оконным свойствам, стилям и другим атрибутам вроде оконной процедуры) из любого потока, и такой доступ является потокобезопасным с точки зрения оконного менеджера, но последовательности загрузки-изменения-записи должны быть ограничены только потоком-владельцем. В противном случае вы окажетесь в условиях гонки вроде такой:
wpOld := GetWindowLongPtr(hwnd, GWLP_WNDPROC); SetWindowLongPtr(hwnd, GWLP_WNDPROC, Cardinal(newWndProc)); function newWndProc(...): LRESULT; stdcall; begin ... CallWindowProc(wpOld, ...); ... end;Если подобные модификации деляются беспечно в любом потоке, то между первыми двумя строками может произойти переключение потоков и второй поток может изменить оконную процедуру окна, приводя к тому, что в
newWndProc
в CallWindowProc
будет передаваться неверная "предыдущая" оконная процедура.Почему тогда Windows позволяет подобные операции потокам, не являющимися владельцем окна? Потому что, как мы все знаем, 16-ти битная Windows была ОС с кооперативной многозадачностью, что означает, что только один поток может быть активен и он не может быть прерван, пока сам этого не захочет. Поэтому указанная выше последовательность кода всегда была безопасна в 16-ти битных Windows. И по соображениям совместимости этот код должен оставаться легальным, даже хотя он более не является безопасным (заметьте, что в попытке ограничить область повреждения, оконный менеджер позволяет менять оконную процедуру только потокам того же процесса, что и поток-владелец окна. Это разумное ограничение, потому что раздельные адресные пространства означают, что адрес функции из другого процесса бессмысленнен в процессе, владеющим окном).
В следующий раз мы посмотрим на контексты устройств (device context).
Комментариев нет:
Отправить комментарий
Можно использовать некоторые HTML-теги, например:
<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>
Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку.
Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.
Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.
Примечание. Отправлять комментарии могут только участники этого блога.