| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Общие вопросы > Оформление кода потока |
| Автор: Alix 1.10.2007, 15:40 | ||||
| Нужно соединить две программы по сети. Использую WinSock2, впрочем это не важно. В каждой жмем "Соединиться" и начинается процесс соединения (кто сервер, кто клиент выбирается checkbox'ом). Процесс состоит из нескольких шагов, например для сервера они такие:
Проблема в том, что этот процесс должен быть в любой момент отменен, т.е. он должен исполняться в отдельном потоке, чтобы срабатывали controls на форме. В то же время поток должен на каждой стадии выводить состояние соединения в форму, в случае же неудачи на любой из стадий он опять таки должен выполнять код, который должен быть синхронизирован. Получается что код метода Execute потока будет выглядеть примерно так:
И мне придется создавать кучу методов аля чтотоТамFailed. А даже если и сделать один метод failed и устанавливать код выхода (failedCode := fcCreateServer), то это тоже кажется страшненьким решением. Впрочем решения красивее я не вижу. Скажите, есть ли оно? Или, быть может, я неправильно использую потоки? |
| Автор: stab 1.10.2007, 15:59 |
| Я в таких случаях делаю события у потока, т.е. все методы вроде updateStatus или чтотоТамFailed находятся внутри класса-потока, а наружу они выдают обычные события в стиле VCL, например: DownloadFailed(Sender: TDownloader; Reason: TFailReason). Не думаю что лучшее решение есть. |
| Автор: Alix 1.10.2007, 17:12 | ||||||||
stab, можно чуть подробнее? Вызов типа
да, конечно, но я имел в виду что код функции execute будет как-то страшненько выглядеть
нет, там используется accept:
|
| Автор: stab 1.10.2007, 18:30 |
всё так же, через Synchronize(DoOnStatusMessage), а в DoOnStatusMessage уже собственно сам вызов обработчика события с параметрами. |
| Автор: Alix 1.10.2007, 18:57 |
| А в чем тогда коренное отличие от моего способа, кроме того, что вызывается какая-то функция на событие? |
| Автор: stab 2.10.2007, 05:33 |
| 1. В том, что для внешнего когда поток может выглядеть как обычный компонент, внешнему коду даже знать не обязательно, что там поток есть. Плюс, обработчки на некоторые события, если они не нужны в каком-то конкретном случае, можно не вешать. В общем, бОльшая гибкость и стандартность подхода. 2. Повышение уровня инкапсуляции, т.к. не требуется объявления в паблик секции свойст вроде StatusText или LastErrorCode, эти данные могут быть просто переданны в обработчик события. В общем, меньше публичных состояний системы - больше надёжности. Если надёжность\реюсабельность\изменяемость кода не важна, эти два пункта - пустой звук. Всё зависит от контекста и объёма задача. |
| Автор: ALeXandrK 2.10.2007, 06:57 |
| http://forum.vingrad.ru/topic-60076.html Там есть все, чтобы удачно применять потоки Пример на твою ситуацию там тоже есть... |
| Автор: Felan 2.10.2007, 07:18 |
| stab, прав. Только вот если так делать, то в события неудобно параметры передавать, т.к. в Synchronaze нельзя вызывать метод с параметрами. Есть еще один вариант. В поточном классе просто сделал синхронизированные свойства которые отражали бы его состояние и позволяли бы управлять этим состоянием. Типа LastStatus - последний статус, в котором находится компонент. Abort - на следующем цикле метода execute прервать операцию и т.п. А на форме можно поставить обычный таймер, для того что бы просто отображать текущее состояние... |
| Автор: Alix 2.10.2007, 08:09 | ||||||
этого и так не делается...
Именно это я и имел в виду, когда говорил, что его код от моего мало отличается.
Никакого управления состоянием быть не должно. Код в потоке выполняется последовательно и там нет циклов. ALeXandrK, про статью знаю, сам выдавал на нее ссылки, в данный момент читаю, хотя и медленно - времени нет. Не подскажете, где там описана моя ситуация? |
| Автор: stab 2.10.2007, 08:13 | ||
а это тогда зачем statusText := 'Создаем сервер...' ?
я как раз таки описал способ как можно передавать параметры в обработчик. |
| Автор: Alix 2.10.2007, 09:27 | ||||
stab, ты написал:
Я понял это так:
В моем же варианте все то же самое, только в DoOnStatusMessage находится не вызов обработчика, а непосредственно его тело. |
| Автор: Felan 2.10.2007, 09:45 | ||
Ну так и не делай его. Все остальное ровно то же самое. Я не пойму чем тебе не нравятся приведенные варианты? Вариант stabа, хорош когда у тебя все на событиях. Мой - когда нужен постоянно следить за состоянием а индикация уже вторична. |
| Автор: Alix 2.10.2007, 09:53 |
| Felan, просто твой вариант мне не подходит, а метод stab'a такой же как и у меня по сути, я просто не вижу разницы между его вариантом и тем, что я привел в первом посте. (кроме, конечно, того, что у него все основано на событиях). |
| Автор: stab 2.10.2007, 10:46 | ||
а, ну ок тогда всё. я подумал что тема про события не была понята |
| Автор: Felan 2.10.2007, 12:15 |
| Alix, По сути ее и нет. Ну можешь еще сообщения посылать. Но это изврат какой-то... Короче, как придумаешь свой уникальный способ - отпишись. Интересно, чего ты там кардинально нового выдумаешь. |
| Автор: Melancholic 4.10.2007, 07:48 |
Тоже думал на эту тему. Приведу общую постановку проблемы в моём понимании:
Какие есть альтернативы? Итак, снова начну с общего описания (это решение я нашел вообще в статье про последовательный порт
Теперь к частностям:
|
| Автор: Felan 4.10.2007, 08:25 | ||
А из этого следует, что ты либо не понял, про что я тебе говорил, либо даже не захотел вникнуть. То, что я тебе предложил как раз и есть решение того, что ты тут написал (Ну или может быть тут ошибочка Т.к. весь ВВ у тебя будет в твоем дополнительном потоке! Обработку этого ВВ можно включить куда угодно. Хоть в твою форму, хоть в то же поток, хоть еще один поток для него завести. А форма будет отображать результаты которые даже можно не мониторить а как раз использовать сообщения, что бы уведомить форму о том, что надо бы обновить результаты таких-то операций. Но это все ИМХО после прочтения твоего ТЗ |
| Автор: Melancholic 4.10.2007, 09:29 |
| Вы правы, Felan, наши варианты похожи. За той лишь разницей что в моём случае поток ВВ сигнализирует о наступлении события посылкой сообщения, а в вашем состояние объекта-потока периодически проверяется таймером формы. Какой из вариантов применять - дело вкуса. Кстати если задача IO нересурсоёмка, то можно вообще использовать асинхронный ВВ, основанный на сообщениях (если кто не в курсе, то винда сама может уведомлять форму о наступлении события на сокете посылкой сообщения - и не надо никаких дополнительных потоков). (см. Использование сокетов в Delphi. Часть вторая: сокеты Windows, Антон Григорьев, дата публикации 01-10-2004 14:52 или описание функции WSAAsyncSelect в MSDN). |