| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: WinAPI и системное программирование > Вопрос по правильной синхронизации |
| Автор: yogin 3.10.2012, 10:16 |
| Приветствую! Имеется такое взаимодействие потоков: MainVCLThread ---(создаёт экземпляр класса)--> TSomeClass --(создаёт экзепляр класса-потока)--> TSomeThread. В классе TSomeClass есть событие OnData(); такое же событие есть и в TSomeThread. Поток обрабатывает клиентский сокет, дак вот когда поток считывает с сокета очередные данные, он должен дать их главному потоку VCL, для этого я и сделал собятия OnData - по ним как по цепочке данные передаются в главный поток. (кстати, попутный вопрос: можно ли оптимальнее сделать эту "передачу по цепочке", т.к. эта цепочка может состоять не только из 2 классов, а больше, тогда можно запариться дублировать события в каждом классе только потому, что самому вложенному надо что-то передать самому верхнему классу, или такая архитектура нормальная?) Сейчас я в потоке вызываю synchronize(DoEvent) и всё работает. Но вопрос в том, как этот вызов синхронайза заменить на что-нибудь, чтобы классы по обработке данных с сокета можно ыбло переносить и использовать как в VCL приложениях, так и в консольных? Я склоняюсь к тому, что надо заменить это критическими секциями(если это не так - критСекции не подходят, то внимательно слушаю вариант), но куда прописать критСекции, где прописать входы и т.п. вот в этом хочу разобраться. |
| Автор: yogin 3.10.2012, 11:59 | ||||||||||
в консольном приложении этот же код встанет(зависнит) на вызове synchronize, т.к. VCL-ом и не пахнет. Вот именно что мне этого и не нужно в некоторых случаях, например при разработке консольного сетевого клиента или когда принимающий сетевой код находится в DLL. В последнем случае даже если DLL подгружается VCL приложением, то синхронайз в длл зависает. Такую проблему я решил как бы не синхронно - просто выызваю событие, которое идёт потом в приложение.
Вот меня именно этот фактор-то и волнует...
Нормальная архитектура, у меня тоже до синхронайза была такая. Просто в новом варианте я стремился сделать всё только на CS, чтобы не делать две версии сетевого клиента(для VCL и не для VCL), но по всей видимости без этого никак... Т.к. консоле постмессагу тоже не отправить. А если выбирать между synchronize и мессагами, то архитектура мессаг мне больше симпатизирует. Я думаю можно поискать как "красиво" посылать синхронные команды консольному процессу.
Полностью солидарен, ну т.е. меня не отпугивает вся эта цепь передач, я просто так поставил вопрос. А вопросом таким задался т.к. пришёл к такой концепции опытом, поэтому как бы задался вопросом "может быть есть что-то оптимальнее, до чего я пока недопёр?...".
Параметры можно брать в любом случае. Например в случае синхронайза удобнее передавать параметры, т.к. это выглядит так:
|
| Автор: Alexeis 3.10.2012, 12:05 |
| Есть еще такое решение, в OnIdle главного потока делать ожидание на MsgWaitForMultipleObjects . Соответственно события от сокетов обрабатывать в главном потоке не вешая его. Вообще, использование второго потока оправданно, когда требуется ждать чего-то или же нагрузка на проц столь велика, что ее неплохо бы распределить на разные ядра. Если же у нас своя очередь обработки сообщений, так даже OnIdle не нужен, а вместо GetMessage использовать MsgWaitForMultipleObjects, соответственно все операции делать в одном главном потоке асинхронно. Очень удобно. Для асинхронных операций использование потоков часто нецелесообразно. |
| Автор: yogin 3.10.2012, 12:22 | ||
Я сделал для клиентского сокета отдельную нить потому что вызов метода TimerProcess() приходилось тянуть из главной нити по цепочке классов-менеджеров сокета, которые "стоят" до класса непосредственного чтения буфера сокета. Хотя их всего два... А т.е. в этом небыло острой необходимости или, можно сказать, мотивация - удобство. Или например, если сетевой код в DLL, то надо было бы создавать експортируемый метод dllTimerProcess() и обязывать, например стороннего, разработчика его вызывать, а иначе с сокета ничего не аукнится... Ещё вероятно я просто напросто имею чрезмерный идеалистический взор на архитектуру... |
| Автор: Alexeis 3.10.2012, 12:40 |
| При асинхронной работе количество сокетов не имеет значения. Сетевая карта, то одна и скорее всего аппаратно может работать только последовательно, так что в отсутствии ожидания отдельный поток никак не улучшает работу. Я также пользовался отдельным потоком для сокетов, в плагинах, но там я все задачи закрывал в этом потоке. Просто для универсальности. Если один плагин косячит, чтобы не вешал единственный рабочий поток. |
| Автор: Чучмек 3.10.2012, 14:39 | ||||
А почемубы не реализовать свой Synchronize
|