Текущий архив: 2003.11.13;
Скачать: CL | DM;
ВнизThread + Win98 = ? Найти похожие ветки
← →
Olexander (2003-09-01 15:17) [0]Привет
столкнулся с такой траблой:
использую TThread для записи в порт
из основного потока постоянно повторяю: послал команду - suspend, принял ответ - resume.
При этом когда минимизирую окно или навожу на кнопку "закрыть" (после появления хинта)- системная ошибка "Параметр задан неверно (87)" или "Така функция не допустима в Вин32"
Хелп - глюк убойный - весь солюшн поганит. Что это может быть ??
Под 2к все ОК.
← →
Digitman (2003-09-01 15:27) [1]
> из основного потока постоянно повторяю: послал команду -
> suspend, принял ответ - resume.
ничерта непонятно ... проиллюстрируй реальным кодом
← →
Olexander (2003-09-01 16:11) [2]по памяти:
TRWthread.execute;
begin
while (not terminated) do
begin
setRts(true);
WritePacket2Port;
SetRTS(false)
Suspend;
end;
end;
..........
// Main thread:
Button1.OnClick()
begin
RWThread := TRwthread.create(false);
end;
apdcomport.OnTriggeravail();
begin
if ReadPacketfromPort then
RWthread.resume;
end;
Сразу идея возникла
- може несколько раз подряд вызываю
Suspend или Resume но в хелпе написано что все должно быть ок
Кстати то же глю если скринсейвер запускается,
или просто форма фокус теряет
← →
Digitman (2003-09-01 16:29) [3]что творится в WritePacket2Port ?
← →
Olexander (2003-09-01 16:52) [4]вообще-то там - synchronize(WritePacket2Port),
забыл,
поскольку на основной форме - компонент ApdComport1, через который общаюсь с портом.
А в функции - просто запись а-ля APDComport.Putblock(Command);
???
← →
Digitman (2003-09-01 16:56) [5]
> вообще-то там - synchronize(WritePacket2Port),
ну и на кой шут такой код.поток нужен ? если вся его основная функц-ть исполняется в осн.код.потоке ?
← →
Verg (2003-09-01 18:31) [6]А с чего ты взял что эти ошибки связаны именно с работой этого потока (Suspend - Resume)? Ты думаешь, что эти функции глючат?
Не смеши...
Может источник ошибки в WritePacket2Port, а может и еще где-то.
← →
Digitman (2003-09-02 08:22) [7]
> поскольку на основной форме - компонент ApdComport1
убери компонент с формы и создавай/уничтожай его динамически в доп.код.потоке.
транспортом данных (прием/передача) с этого момента будет "заведовать" искл-но лоп.код.поток, и синхронизация с осн.код.потоком, думаю, не потребуется вовсе
← →
Polevi (2003-09-02 10:11) [8]А вообще недостаточно информации для анализа - неизвестно как работает этот ApdComport, например ComPort by Dejan Crnila сам занимается синхронизацией и события типа OnRead, OnWrite работают в основном потоке у него - то есть доп кодовый поток у него уже есть свой. Весьма вероятно что у ApdComport тоже есть доп. поток, по крайней мере если бы я стал писать подбный компонент - сделал бы точно так
← →
Olexander (2003-09-02 11:16) [9]2 Verg © (01.09.03 18:31) [6]
> А с чего ты взял что эти ошибки связаны именно с работой
> этого потока (Suspend - Resume)? Ты думаешь, что эти
> Может источник ошибки в WritePacket2Port, а может и еще где-то.
Опять важную деталь забыл. Ошибка Thread error: wrong parameter (87). Посему и думал, что это с потоками - кода там немного
(запис в порт, чтение), складывание в память
-----------------
ОК, попробую описать задачу
Буду очень блогодарен за идеи по поводу архитектуры.
Если в пределах досягаемости от Киева - даже пивом.
С портами и потоками раньше не работал, посему проблемы.
/
Есть прибор с которым нужно общаться через модем на 1200 бод.
- Протокол связи примерно такой (дано):
команды (пакеты) по 20 байт. Прибор - ведомый - только отвечает на команды, сам связь не инициирует.
Если прибор команду принял - отсылает ответ в том же формате обратно. Если мы ответ от прибора не получили - посылаем команду опять - так несколько раз, потом стоп. Каждой посланной команде соответсвует один ответ. Да, еще: в канале постоянно мусор и помехи, из всего этого потока нужно выхватывать команду.
Посылаем команду - ждем ответ, если приняли - посылаем следующую.
- Система команд:
Несколько управляющий (включить, выключить, начать набор информации), и команды собственно с данными (запрос на данные и ответ с данными).
- последовательность работы (посылки команд):
включить прибор
ждем 30 сек
начать набор информации
ждем 60 сек
передать наверх измеренные данные (у прибора свой буфер, в котором он накапливает, потом оттуда можно это все считать) - порядка 120 пакетов.
....
Всего один цикл измерений - несколько минут. Начало цикла инициируется пользователем.
Так вот, как только (если) получили измеренные данные - тут же осредняем, корректируем, ляля..., и выводим на экран - в виде таблици и графика - чего мы там намеряли.
Понятно, в это время прога не должна виснуть - а отвечать на действия юзера.
Сейчас у меня примерно так:
все вместе еще не собрал - пока не представляю как.
Пока написал ГУИ и отработал связь (посылка- выхватывание ответа из потока мусора), в разных прогах. как связать вместе - пока не представляю.
Для порта использую Async Pro GNU-шный. Бросил его на форму, посему из пишущего потока к нему обращаюсь через Synchronize. Соответственно, обработчик события на приход данных - в основном потоке, а пишу в порт из дополнительного (чтоб не было вислова). Наверное тупо, но пока по-другому не умею.
Если можно включить прямо в поток - супер - но я пробовал - не получилось, до конца пока не разобрался.
Еще прикол в том, что оригинальный софт был под ДОС - там все в реальном режиме, не теряется, никаких задержек и т.д. Тут, если начинаю играться с приоритетами - то не все пакеты уходят, то не все приходят. А 98 и 2к похоже по-разному с портами работает... ну это так...
Ну собственно вопрос - как лучше сделать (можно с рисунками :).
Где держать компонент, сколько потоков заводить, откуда писать/читать, как синхронизировать все это дело (если нужно).
Спасибо кто дочитал пост до конца - жду и надеюсь...
Кстати, по мылу наверное удобнее будет обсуждать.
← →
Polevi (2003-09-02 11:40) [10]> Наверное тупо, но пока по-другому не умею.
тупо
какие события есть у компонента ? если нет событий типа OnRead - ожиданием данных должен заниматься доп кодовый поток, а не основной, иначе нет смысла.. посмотри исходники как реализованы ф-ии записи и чтения
← →
Olexander (2003-09-02 12:13) [11]
> > Наверное тупо, но пока по-другому не умею.
> тупо
>
> какие события есть у компонента ? если нет событий типа
> OnRead - ожиданием данных должен заниматься доп кодовый
> поток, а не основной, иначе нет смысла.. посмотри исходники
> как реализованы ф-ии записи и чтения
Ну так в том то и дело что есть.
Кажись начинаю понимать...
Если есть обработчик - значит чтение выполняется где-то в отдельном потоке в компоненте, верно? Даже если компонент на основной форме. Значит смысла писать свой нету. Так бы пришлось делать поток, который по циклу постоянно опрашивал бы порт на наличие данных. Но обработчик который я напишу для OnRead будет выполняться в основном потоке ? Там кода немного: складывание в буфер и - попытка распознать ответ. Стоит ли его выносить в отдельный поток, или это я уже загнул?
Вот только что нашел в доке:
компонент создает три потока - один для событий (WaitCommEvent)
второй для чтения, третий для записи.
Начинаю потихоньку понимать...
← →
Polevi (2003-09-02 12:32) [12]>Стоит ли его выносить в отдельный поток, или это я уже загнул?
загнул, нет смысла, разве что "Там кода немного" будет долго выполянться, что врядли - обработчик должен отработать максимально быстро, иначе может переполниться буфер порта и данные "потеряются"
← →
Digitman (2003-09-02 13:20) [13]
> Но обработчик который я напишу для OnRead будет выполняться
> в основном потоке ?
он будет выполняться в том потоке, который вызвал этот обработчик
вызывается ли обработчик в основном или доп.потоке, проверить оч просто :
if GetCurrentThreadId = MainThreadId then
.. основной.... (с некоторой оговоркой)
else
.. дополнительный
вставь эту проверку первыми строками в обработчик того или иного события - сразу сориентируешься
p.s.
а OnWrite() - есть событие такое ?
← →
Olexander (2003-09-02 15:10) [14]
> он будет выполняться в том потоке, который вызвал этот обработчик
>
> вызывается ли обработчик в основном или доп.потоке, проверить
> оч просто :
>
> if GetCurrentThreadId = MainThreadId then
> .. основной.... (с некоторой оговоркой)
> else
> .. дополнительный
>
> вставь эту проверку первыми строками в обработчик того или
> иного события - сразу сориентируешься
>
> p.s.
>
> а OnWrite() - есть событие такое ?
Ок, понял
а если обработчик все же в основном потоке и в нем я определил, что получил все пакеты и мне надо запустить длинную процедуру (обработка, отображение, запись в файл) - как это сделать ??
Чтоб не загружать его ?
← →
Polevi (2003-09-02 15:11) [15]создай доп поток, передай ему данные и запусти
← →
Olexander (2003-09-02 15:12) [16]
> а OnWrite() - есть событие такое ?
Это, я так понимаю, после записи ?
есть событие очистки исходящего буфера компонента
а зачем ?
← →
Digitman (2003-09-02 15:53) [17]
> а зачем ?
а затем, чтобы не ждать пока исх.буфер освободится !
предположим, обработчик OnRead() выполняется в осн.потоке
тогда, чтобы не "тормозить" осн.поток обработкой данных, создается доп.поток
в обработчике данные, полученные в OnRead(), помещаются в хвост некоей очереди данных на обработку. Доп.поток тут же извещается о том, что очередь непуста. Доп.поток выбирает из головы очереди данные, обрабатывает их и помещает результаты обработки в хвост другой очереди (очереди результатов), немедленно извещая осн.поток о том, что последняя непуста. Осн.поток в обработчике события освобождения исх.буфера берет из головы очереди результатов очер.порцию (не более размера исх.буфера) и вызывает асинхр.метод передачи.
по
← →
Olexander (2003-09-02 16:27) [18]
> в обработчике данные, полученные в OnRead(), помещаются
> в хвост некоей очереди данных на обработку. Доп.поток тут
> же извещается о том, что очередь непуста. Доп.поток выбирает
> из головы очереди данные, обрабатывает их и помещает результаты
> обработки в хвост другой очереди (очереди результатов),
> немедленно извещая осн.поток о том, что последняя непуста.
*
> Осн.поток в обработчике события освобождения исх.буфера
> берет из головы очереди результатов очер.порцию (не более
> размера исх.буфера) и вызывает асинхр.метод передачи.
> по
До звездочки все понял, примерно так я себе это интуитивно представлял.
А результаты мне передавть никуда не надо - только отображение и сохранение.
У меня вырисовывается примерно такая процедура:
1. формируем очередь пакетов на отсылку
2. запускаем поток, который только пишет.
он пишет одну команду, останавливается, ждет ответ
3. если получили корректный ответ (в основном потоке) -
добавляем в очередб принятых и резюмим поток записи.
4. если все отослали и приняли все ответы - запускаем обработчик (еще один поток) полученных данных, который отображает, сохраняет и т.д.
5. В это время можно формировать новую очередь на отсылку.
--------
Кстати как реализовать это самое "извещает" (запуск/останов)?
Нашел про TEvent и TThread.Waitfor - годится ??
TEvent меня не впечатлил - или толком не разобрался как он работает.
--------
Еще вопрос - если у меня компонент на форме - можно ли напрямую обращаться к нему из доп. потока или надо синхронизировать ?
--------
И еще один:
всего получается 2 моих доп. потока + три потока компонента
не много ?? Винда нормально справляется с такими наворотами?
А то у меня ощущение что это все будет глючить...
Спасибо
← →
Digitman (2003-09-02 16:33) [19]
> TEvent меня не впечатлил - или толком не разобрался как
> он работает.
вот как раз TEvent и не самое плохое решение !
> если у меня компонент на форме - можно ли напрямую обращаться
> к нему из доп. потока или надо синхронизировать ?
однозначного ответа нет, все зависит от "поторохов" компонента
убери его с формы ! и проблемы не будет
Страницы: 1 вся ветка
Текущий архив: 2003.11.13;
Скачать: CL | DM;
Память: 0.51 MB
Время: 0.046 c