Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

потоки [D6, D7, WinXP]


Страницы:   1 2 3

Mixal__ ©   (2006-12-06 07:26:00) 

Добрый день. Вот такой вопрос профессионалам:
Есть программа создающая отдельный thread, в котором идёт опрос устройства(обращение к COM порту посредством ReadFile/WriteFile) через промежутки времени (sleep). В основной программе также есть обращения к этому устройству. Дело в том, что устройство может обработать последующий запрос только спустя некоторое время(время обработки запроса).  Вызовы из потока могут наступить в любое время, когда ещё не обработан устройством вызов из главной программы. Каким образом можно исключить такую ситуацию?


Mixal__   (2006-12-06 12:46:00) [21]

Вобщем смысл понятен... Но всётаки несовсем понятно, почему обязательно использовать механизм, при котором работа с портом будет происходить из одного потока...
Например я вставлю посылку/приём команды например в отдельную процедуру, в которой буду юзать критическую секцию:

1. EnterCriticalSection
2. WriteFile - пишу в порт
3. ReadFile - читаю ответ
4. sleep - подожду пока устройство подготовится к приёму новой команды
5. LeaveCriticalSection

Эта процедура будет вызываться из моего потока например раз в секунду...и вот она вызвалась.... во время нахождения в критической секции юзер жмёт кнопку и вызывается процедура получения прошивки, в которой есть вызов этой же самой функции, которая работает с портом, но она в данный момент занята и придётся подождать... прога ждёт выполнения... потом входит и работает с портом. и вроде всё ок...
Чтото не так?
И чем заменить sleep раз он такой глючный...


С   (2006-12-06 12:22:00) [22]

Ну получило устройство новый запрос во время обработки предыдущего. Кто ему мешает тут же отправить ответ типа "отвали, я занято"? Опчть же, если устройство по результу обработки запроса выдает ответ, то кто мешает использовать сей факт как индикатор готовности. А если не выдает, то кто мешает заставить его ответ выдавать, раз устройство тобой и разработано. Впрочем, как знаещь


Сергей М.   (2006-12-06 11:59:00) [23]


> Mixal__   (06.12.06 11:34) [20]


Да, общий смыл ты уловил.
Только нужен не флаг, а две полноценных очереди - одна для запросов, другая для результатов их выполнения.

Трансп.тред выбирает из очереди запросов очередной запрос.
Элемент этой очереди = уник.идентификатор запроса + кто послал + команда + необходимо ли возвратить результат исполнения запроса).

Далее тред исполняет запрос и , если необходимо, помещает его результат в очередь результатов.
Элемент этой очереди = уник.идентификатор запроса  + собственно результаты его выполнения


Mixal__   (2006-12-06 11:57:00) [24]

2C

Извещать хосту устройство не может,т.к по своей инициативе не передаёт данные, только путём запрос/ответ.


C   (2006-12-06 11:44:00) [25]

Mixal__   (06.12.06 11:34) [20]
Если устройство свое, то кто мешает сделать так, чтобы оно извещало хост о завершении обработки полученной команды, если уж во время обработки нельзя отвлечься на запись в буфер передачи одного байта - влага "занято". Или все-таки можно?:)


Mixal__   (2006-12-06 11:34:00) [26]

2Kolan ©
>> 150мс это точно гарантированное время

>Ну поверь что так делоть нендо.

Как же ещё сделать то? Как узнать, занято в данный момент устройство выполнением предыдущей посланной команды? да никак.... проще уж подождать немного и уже потом с уверенностью засылать следующую команду.

2Сергей М. ©

Как я Вас понял будет выглядеть примерно так...?

какой-то глобальный флаг имеющейся команды

var flag:bool=false;  

и некий "буфер" для хранения команды

var cmd:...

потом идут функции, которые вызываются программой

function Cmd1.(....):....;
begin
cmd = чтото
flag:=true;
end;
.
.
.

function CmdN.(....):....;
begin
cmd = чтото
flag:=true;
end;

затем в потоке

while(not terminated)do begin
 if(flag)then begin
  doCmd(cmd) ;  // послать команду
  flag:=false;
 end;
...
чтото - ещё
...

end;


С   (2006-12-06 11:19:00) [27]

Я в курсе от чего и насколько оно зависит. И частота процессора в этот список если и входит, то в самой наименьшей степени


Kolan   (2006-12-06 11:13:00) [28]

> [17] C   (06.12.06 11:07)
> Kolan ©   (06.12.06 10:40) [12]
> Windows - не есть система реального времени.
>
> Это понятно. Непонятно, с чего бы ей превращаться в хз,
> да еще и зависеть от тактовой частоты процессора.

Зависит много от чего. И от запушеных программ итд.. Да че уговаривать, делай так потом программу заказчику отдашь и повеселишся :). Я слава богу лично не обжигался, люди же уже все это прошли.


C   (2006-12-06 11:07:00) [29]

Kolan ©   (06.12.06 10:40) [12]
Windows - не есть система реального времени.

Это понятно. Непонятно, с чего бы ей превращаться в хз, да еще и зависеть от тактовой частоты процессора.


Reindeer Moss Eater   (2006-12-06 11:06:00) [30]

Вызовы из потока могут наступить в любое время, когда ещё не обработан устройством вызов из главной программы. Каким образом можно исключить такую ситуацию?

Чтение с помощью оверлдапед евентов.
После очередной операции записи взводить флаг, сигнализирующий, что ожидается команда.
Пока флаг не сброшен, не посылать в порт новых команд.
Флаг сбрасывать когда состоялось чтение.


Kolan   (2006-12-06 10:57:00) [31]

> устройство пассивное - никогда не передаёт само данные,
> только по запросу

Отлично так и должно быть Запрос-ответ.

> 150мс это точно гарантированное время

Ну поверь что так делоть нендо.

значит юзать семафоры надо
Да что хочешь

Еще раз, алгоритм такой.
1. Есть "менеджер устройства", который реализует все доступные функции устройства.
2. У менеджера есть очереть(TQueue непример).
3. Кто угодно проситменеджера опросить устройство.
4. Он кладет запрос в очередь.
5. Если очередь не пуста он посылает запрос через порт и ждет ответ. Если ответ есть то все ок если нет - ошибка связи.

Пример:

Пусть у уср-ва 2 комманды:
1. Получить данные.
2. Получить версию прошивки.

И есть два потока:
1. Главный
2. Поток опроса.
3. Поток менеджера устр-ва

Поток опроса каждую сек. посылает запрос "Получить данные" и в это время пользователь нажалд кнопку "Спросить версию".

1. Поток в "менеджере устр-ва" смотрит что очередь пуста ниче не делает.
2. Поток "опроса" добавляет коммаду получить данные
3. Поток менеджера смотрит что очередь не пуста отправляет комманду через порт, ждет, если ответ получен возвращает его.
4. Поток "опроса" добавляет коммаду получить данные и так далее.
5. Вдруг пользователь жмет на конпку "Получить версию прошивки". И гл поток тоже добавляет комманду "Версия прошивки".

Те очередь будет такая:

Получить данные
Спровить версию
Получить данные


6. Ну х сним, поток менеджера знай себе выбирает комманды да отробатыавает их. Сначала он получит данные, затем спросит версию, затем опять данные.

Как видишь из разных мест и потоков я работаю с пом 1 единственного(его надо сделать синглетоном) объекта - "менеджера устр-ва".

Вот как-то так. Тук работы прилично... Асинхронизировать оч просто TCriticalSection.


Сергей М.   (2006-12-06 10:48:00) [32]


> Mixal__   (06.12.06 10:40) [13]


Тогда ничто не мешает использовать твой доп.поток как транспортный. Он будет заниматься и "слежением" и обслуживанием запросов прочих потоков на ввод/вывод


Kolan   (2006-12-06 10:40:00) [33]

Windows - не есть система реального времени.
Sleep(150) читать надо так:
-Дорогая Windows немогла бы ты усыпить поток на, примерно, 150 мс если конечно можно.
[Ответ системы] - Я конечно попытаюсь но ничего не обещаю

:)


Mixal__   (2006-12-06 10:40:00) [34]

Очередь запросов... значит юзать семафоры надо?
2Kolan ©
>Зачем опрос всегда? Только по событию.

устройство пассивное - никогда не передаёт само данные, только по запросу. Постоянный опрос необходим для слежением за состоянием устр-ва.

2clickmaker ©
150мс это точно гарантированное время *5 обработки команды устройства   - т.к. устройство не "какое-то" а "своё"

2Сергей М. ©

>Что-то я не понял, каким образом создаваемый тобой поток умудряется >открыть СОМ-порт, если он уже открыт в это время другим потоком ?

Порт открывается при инициализации длл. В длл порт юзают из потока и из функций, вызываемых программой, подключившую длл.


C   (2006-12-06 10:33:00) [35]

Kolan ©   (06.12.06 10:07) [8]
>> Sleep(150); // жду когда команду обработает устр-во гарантированно

>Во-во, а теперь пойди на Pentium II и на Intel Duo Core и тои 150 превратятся в хз сколько...


Почему?


Kolan   (2006-12-06 10:09:00) [36]

Ой, недописал...

> Также есть вызываемые в любой момент из dll функции, которым
> также необходимо работать с устройством...

Тут видимо очередь и будет.
У "Менеджер устр-ва"(или у кого то еще) должна быть очередь запросов.


Kolan   (2006-12-06 10:08:00) [37]

> При инициализации dll создаётся поток в котором идёт опрос...

Зачем опрос всегда? Только по событию.


Kolan   (2006-12-06 10:07:00) [38]

> Sleep(150); // жду когда команду обработает устр-во гарантированно

Во-во, а теперь пойди на Pentium II и на Intel Duo Core и тои 150 превратятся в хз сколько...


> Сделать работу с устр-вом в одном месте тоже врятли получится...

Не в одном месте, а так сказать через одно место :).

Нужно сделать "Менеджер устр-ва".
Иесли кому-то  нужно обратиться к устройству, то он обращетеся к "Менеджеру".

А менеджер уже разбирается с портом и тд...


> Не использовать поток не получится

Так никто и не отговаривает делай пток для работы - это удобно.


Сергей М.   (2006-12-06 10:01:00) [39]


> Mixal__


Что-то я не понял, каким образом создаваемый тобой поток умудряется открыть СОМ-порт, если он уже открыт в это время другим потоком ?


clickmaker   (2006-12-06 09:51:00) [40]


> И с чего Sleep должен глючить... этож функция виндов....

для критических по времени приложений лучше использовать события. А так - много допущений. Почему именно 150? Где гарантия, что именно за это время что-то там "команду обработает"? Не лучше ли когда обработчик команды сам скажет, что он закончил?


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо