![]() |
|
Модераторы: Snowy, Poseidon, MetalFan |
![]()
|
|
| artymen |
|
|||
|
Кодер Профиль Группа: Участник Сообщений: 14 Регистрация: 23.8.2007 Репутация: нет Всего: нет |
Среди множества статей по работе с TSocketServer/Client я нашел только одну небольшую статью по работе в блокирующем режиме. К сожалению она отразила лишь небольшой эпизод из жизни готовой программы-"шаблона". Справочная система делфи тоже не дает ответов. Поэтому вопросов у меня много, ибо моя программа все еще рабоатет неидеально, но по мере продвижения она все реже и реже выдает "Access Violation". Скажу сразу, что многопоточность я изучил достаточно досканально и уже настардался с нею, если мне не поможет кто-то извне, я кончу психушкой.
1. Правильно ли я понимаю "thread-safe code": потокобезопасный код, эта необходимость обусловлена выполнением кода не в VCL-потоке ? 2. В справке написано что в OnClientDisconnect нужно использовать как раз потокобезопасный код. Про другие события этого не сказано. У меня возникают соменния что все остальные события выполняются к контексте VCL-потока. 3. Поведение TServerClientThread очень сильно отличается от обычного TThread. Попытка работать с ним как с TThread приводит к катастрофическим последствиям. Попытки инициализировать поток в OnThreadStart, созданный мною в OnGetThread, приводят к краху, я пробовал это дело контролирвать различными комбинациями приостановки/возобновления потока, результат тот же. Поток завершится (сработает OnThreadEnd) только если я принудительно завершу его в OnClientDisconnect, получив его там из GetClientThread. WaitFor не возварщает управление никогда, даже если он вызван сразу же после Terminate. Вобщем полная неразбериха. 4. Отладка вообще дело мистическое. Когда я трейсю, все рабоатет иделально, как будто дебагер все "смягчает" (например можно спокойно в потоке напрямую обращаться к форме). Таким образом я даже не могу отследить в каком месте кода проиходит сбой ! Могу лишь докадыватсья в каком районе. 5. TEvent (сигнализируемый объект). Он "потокобезопасен" ? Т.е. обязательно ли при обращении к нему (разумеется кроме ожидания сигнала при помощи WaitFor) использовать, например, критические секции ? В потоке я обращаюсь к только к компоненту мемо формы, через Synchronize и очень редко. Вся работа потока заклчюатся в работе с сокетом посредством чтения/записи в TWinSocketStream и работы с процессами (перчисление процессов средствами JwaPsApi (Jedi), открытие, ожидание завершения (WaitForSingleObject) либо принудительное завершение процесса) и с событиями (TEvent). При этом потоки никакими данными не обмениваются, но синхронизируются между собой при помощи событий TEvent (я обрабатываю случаи когда поток ждет события которое уже уничтожено), таким образом я организую очередь клиентов, потому что сервер согласно своей функциональности не способен обрабытвать запросы нескольких клиентов одновременно. Код потока у меня обрабатывает исключения, а так же он весь напичкан проверками на Terminated, так что при запросе завршения он в любой точке работы закончит свою работу не дольше чем через 500 мс. Как вы наверно догадались, моя программа достаточно большая, поэтому я не поместил ее сюда, а описал самые важные моменты ее реализации. На данный момент она сбоит примерно на каждом 6-ом клиенте. Буду очень благодарен, если вы прочитаете хоть что-то из моей огромной писанины и поможете разобраться хоть в одном из вопросов/проблем. Если я разберусь во всем, то обещаю написать исчерпывающую статью о том, как работать в блокирующем режиме с TServerSocket. |
|||
|
||||
| dumb |
|
|||
![]() sceloglauxalbifacies ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 2929 Регистрация: 16.6.2006 Репутация: 5 Всего: 158 |
ты кончишь психушкой.
1. да. 2. все, что начинается на OnClient и на OnThread - должно быть thread-safe. 3. отличается, хотя и наследник. НО. в TServerSocket используется пул потоков, т.е. при отключении клиента потоки не уничтожаются, а ждут повторного использования. OnThreadStart вызывается уже из Execute, поэтому инициализировать там можно далеко не все. 4. подробное протоколирование в файл каждого "чиха". функцию лога на критическую секцию. 5. TEvent - thread-safe. никаких крит.секций не нужно.
|
|||
|
||||
| artymen |
|
|||
|
Кодер Профиль Группа: Участник Сообщений: 14 Регистрация: 23.8.2007 Репутация: нет Всего: нет |
Спасибо ! Психушка тепреь от меня очень отдалилась !
И как же мне в обработчиках событий безпопасно обраться к форме, если там нет Synchronize ? Наверно придется через PostMessage. PS. Насчет обмена данными между потоками. Забыл, что поток читает глобальную пременную, но это делается в Synchronize. Вряд ли это имеет значение, но все же. |
|||
|
||||
| Felan |
|
||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 284 Регистрация: 2.8.2007 Где: Самара Репутация: нет Всего: 7 |
Вот здесь как раз критические секции. Если у тебя есть объект на форме, который тебует изолированного доступа, то делаешь критическую секцию и методы доступа к объекту, которые будут работать через эту критическую секцию.
Если у тебя к ней, кроме твоего потока, имеет доступ только поток VCL, но не имеет, а если еще один (например поток соединения сокета), то нужно делать ручную синхронизацию. Synchronize используется ИСКЛЮЧИТЕЛЬНО ДЛЯ СИНХРОНИЗАЦИИ С ПОТОКОМ VCL!!! ЗЫЗ Странно вообще-то видеть такие вопросы в свете сказанной тобой фразы
-------------------- // Любая сложная система - это темный лес. Каждый в этом лесу протаптывает свои тропинки, по ним и бегает. Лишь изредка, сходя с них, мы находим много интересного, а порою и страшного. |
||||||
|
|||||||
| artymen |
|
|||
|
Кодер Профиль Группа: Участник Сообщений: 14 Регистрация: 23.8.2007 Репутация: нет Всего: нет |
УРААА !!!
Все нормально, потому что: 1. К тем переменным не обращаются другие потоки, иначе бы я это сказал и не пихал бы смело в Synchronize. 2. Тут поток особенный, поэтому у меня вопросы/сомнения насчет традиционной работы с этим потоком. |
|||
|
||||
| artymen |
|
|||
|
Кодер Профиль Группа: Участник Сообщений: 14 Регистрация: 23.8.2007 Репутация: нет Всего: нет |
И еще последний вопрос насчет TWinSocketStream.WaitForData(). В справке написано
|
|||
|
||||
| dumb |
|
|||
![]() sceloglauxalbifacies ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 2929 Регистрация: 16.6.2006 Репутация: 5 Всего: 158 |
WaitForData - ожидание приходящих данных. причем тут "write" - я не понял, так как она просто select на read-события сокета делает... нужна скорее для "ручного" вычитывания данных из сокета, нежели для того, о чем написано в справке... есть подозрение, что ты ее можешь вообще убрать.
|
|||
|
||||
| artymen |
|
|||
|
Кодер Профиль Группа: Участник Сообщений: 14 Регистрация: 23.8.2007 Репутация: нет Всего: нет |
Отлично, так и сделаю
|
|||
|
||||
| artymen |
|
|||
|
Кодер Профиль Группа: Участник Сообщений: 14 Регистрация: 23.8.2007 Репутация: нет Всего: нет |
Мда, убрал WaitForData'ы - стабильность исчезла
|
|||
|
||||
| dumb |
|
|||
![]() sceloglauxalbifacies ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 2929 Регистрация: 16.6.2006 Репутация: 5 Всего: 158 |
||||
|
||||
| artymen |
|
|||
|
Кодер Профиль Группа: Участник Сообщений: 14 Регистрация: 23.8.2007 Репутация: нет Всего: нет |
Все нормально, это я накосячил. Я убрал wait'ы и забыл что далее, будучи увереным после wait'а, что данные пришли, через ReadBuffer читал, а таймаут я для этих операций маленький сделал, поэтому генерировалось исключение.
У меня теперь другой вопрос насчет Write метода. В справке очень неясно описана мелкая, но очень важная деталь:
|
|||
|
||||
| artymen |
|
|||
|
Кодер Профиль Группа: Участник Сообщений: 14 Регистрация: 23.8.2007 Репутация: нет Всего: нет |
статья откладывается на неопределенный срок =)
|
|||
|
||||
![]()
|
| Правила форума "Delphi: Сети" | |
|
|
Запрещено: 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делится вскрытыми компонентами
Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Snowy, Poseidon, MetalFan. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Delphi: Сети | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |