COM объект по работе с компортом.засада с WaitforSingleObject #384002


#0 by spenov
задача - получать с картридера считанный код и если все соответствует правилам, то открывать замок. чтение карты и управление замком по компорту(rs232). чтобы это происходило в фоновом задании на сервере, сделал COM объект, в котором реализована работа с ридером и замком. в задании крутится такой цикл: так вот в комопненте ожидание реализовано с помощью WaitforSingleObject. и в потоках идет опрос соотв компортов. как только в компорте есть данные, устанавливается событие (через PulseEvent) и основной поток должен проснуться и выдать в 1с информацию. тестовая программа, сделанная на delphi отлично работает с компонентой. 1с7.7. также работает как часы. в 1с8 событие (просыпается основной поток и передается управление в 1с) происходит только кадый третий раз (т.е. 2 раза считываешь карту - ничего не происходит, на третий раз срабатывает). при этом само считывание данных из компорта отрабатывает как надо. и на третий раз 1с получает информацию за все три раза (т.е. 3 кода). не понимаю почему так. может кто знает как с этим бороться?
#1 by ТелепатБот
#2 by Torquader
Есть мнение, что задание выполняется не слишком часто, а события успевают накапливаться.
#3 by Torquader
Я бы для опроса Com-портов использовал SetCommMask и WaitCommEvent. Лучше использовать функцию MsgWaitForMultipleObjects, которая, кроме всего прочего, прерывается на обработку очереди сообщений - чтобы было нечему подтормаживать (очередь сообщений используется для многопоточного обмена по Ole). Может оказаться, что посланное тобой в 1C сообщение будет ждать второго цикла выхода из WaitForSilgeObject - ну или поставить минимальный TimeOut а потом Sleep, чтобы квант потока отдать системе.
#4 by spenov
да там тормозить нечему. запускаю 1с, в ней тестовую обработку. шлеп картой. пошел сигнал. и только на третий шлеп WaitforSingleObject получает сообщение. хотя PulseEvent отрабатывает без ошибок. если аналогичную обработку запускать в 1с7.7 , то все работает нормал. если пользоваться объектом в проге, написанной на дельфи (там всего то несколько строк), то тоже все нормал. проблема именно в 1с8. каким то образом она блокирует сообщения для WaitforSingleObject. тормозить там вообще нечему...понятно что это глюк. ворпрос в том, можно ли его как то обойти. компонет для того и делал, чтобы задание выполнялось постоянно. я же привел текст кода задания. оно крутится на постоянке при старте сервера 1с. в цикле считывает сообщения от картридеров. всю эту канитель пришлось придумывать потому что внешние компоненты оказывается использовать в серверном коде нельзя.
#5 by Torquader
В 1С7.7 нет сервера - поэтому там всё работает. В 8: Насколько я понял, ты создаёшь свой OLE-объект, который 1С всё время опрашивает. Мне кажется, что тормоза связаны с тем, что 1С просто не доходит до Wait. Попробуй сделать трассировку - закатать в файл время прохождения всех контрольных точек основного потока. И ещё - объект в DLL или в EXE ?
#6 by Torquader
Как 1С узнаёт, что произошло событие ?
#7 by spenov
в 1с8 не работает в обоих вариантах.и в сервере и в клиенте. 1с ничего не узнает.все зашито в компоненте, в методе WaitForEvent. когда он возвращает 1, значит в компоненте есть считанное значение, оно возвращается методом EventMsg. ничего не тормозит, загрузка проца 0. для этого и используется WaitforSingleObject. пишется это все не в 1с, а на любом нормальном языке. используется интерфейс комобъекта по причине отсутствия механизма внешних компонент в сервере 1с.
#8 by ШтушаКутуша
потоковая модель в 1С 7.7 "single"-один есдинственный поток без распараллеливания и не требующий синхронизации, в 8-ке потоковая модель другая, там требуются синхронизации. Возможно из-за этого конфликт
#9 by spenov
а причем здесь потоковая модель 1с?! вспоминаем основные принципы ООП...
#10 by ШтушаКутуша
:))))))))) а причем здесь ООП?!
#11 by spenov
ну немного теории тогда. инкапсуляция. означает что потребителя абсолютно не интересует (да и не может узнать) способ получения необходимого результата. важен сам факт получения этого результата. есть класс, который доставляет в 1с считанные коды. как он это делает для 1с без разницы. 1с не может повлиять на процесс формирования результата классом и класс не может повлиять на поведение 1с. но это теория. а на практике бывают вот такие залепухи...
#12 by spenov
забыл добавить, что больше дискутировать не буду. жду практических рекомендаций по обозначенной проблеме :)
#13 by Torquader
У тебя COM-объект в DLL или в EXE ? Просто, если в DLL, то он живёт в адресном пространстве 1С. Если в EXE, то это самостоятельное приложение. Функции твоего объекта вызываются через интерфейс IMarshal для передачи данных. Если в DLL, то может вызываться програмно, но в случае, если в сервере два процессора, то два потока могут быть на разных процессорах, что может приводить к любопытным эффектам взаимодействия. Попробуй поставить CriticalSection при обращении к переменной, хранящей число несчитанных событий. Кроме того, есть мнение, что нужно давать не PulseEvent, а SetEvent, а сбрасывать событие только тогда, когда его данные прочитали. Ещё лучше в каждый поток встроить процедуру добавления события в основной список событий (с критической секцией), а основному потоку просто "дать отдохнуть". Если же используется DLL, то вообще нет смысла создавать поток для учёта событий, так как тебя будет "дёргать" сама 1С, а каждый порт будет сам фиксировать всё, что было прочитано.
#14 by spenov
у меня dll. думаю что если сделать в exe, то будет работать. но во первых, это надо опять все переделывать, во вторых не очень мне нравится отдельный процесс. проблема в том, что до считывания событий дело не доходит. Сперва использовал SetEvent. Потом стал использовать PulseEvent. Ведет себя одинаково, событие срабатывает только на третий раз. критические секции естественно используются, при обработке общих ресурсов. в том то и дело, что 1с не дерагает сама, а ждет когда поступит сигнал на обработку события. т.е. запущенное задание постоянно крутит цикл. это специфика фонового задания. если делать в клиенте, то можно использовать внешнюю компоненту и обработку внешнего события. но в серверном варианте всего этого нет.поэтому и появилось такое решение. и всебы хорошо, если бы не глюк с событиями. если никто в ближайшее время не подскажет решение проблемы, то придется отказываться от фоновых заданий и запускать клиента под обработку этой задачи. либо отказываться от 1с, но в этом случае придется городить импорт/экспорт из 1с (не красиво это)
#15 by spenov
все оказалось просто. у меня WaitForEvent было реализовано как свойство (для чтения). а 1с8 читает его 3 раза. поэтому и приходилось давать 3 сигнала от устройства. т.е. сообщения доходили. изменил реализацию, сделал методом. все заработало как надо! изменения в коде такие:        ...
Тэги:
Ответить:
Комментарии доступны только авторизированным пользователям

В этой группе 1С