Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Система";
Текущий архив: 2003.11.13;
Скачать: [xml.tar.bz2];

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.03 c
1-41589
VaZa
2003-10-24 23:24
2003.11.13
Список установленых программ


4-42271
w666w
2003-09-10 17:50
2003.11.13
Как уничтожить спящий или подвисший поток?


8-41764
Ig
2003-07-03 21:55
2003.11.13
Как сделать скин для проги


3-40879
DevMaster
2003-10-20 17:59
2003.11.13
Какую СУБД выбрать???


1-41609
frogl
2003-10-24 16:12
2003.11.13
Копирование в TWebBrowser





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский