Hmm 0 28 марта, 2012 Опубликовано 28 марта, 2012 · Жалоба ... классный класс. Да неплохой. Использовал под C++Builder что-бы не нарушать лицензионного соглашения. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dm37 0 26 сентября, 2016 Опубликовано 26 сентября, 2016 (изменено) · Жалоба в архиве cport310 есть файл readme.txt всё (правда по английски) написано а если кратко, то так (на примере Delphi 7): - открываем в Delphi файл cport-3.10\sources\CPortLib7.dpk - в открывшемся окне "Package - CPortLib7.dpk" жмём кнопку "Compile" - закрываем окно "Package - CPortLib7.dpk", но запрос "Сохранить" жмём "Нет" - открываем в Delphi файл cport-3.10\sources\DsgnCPort7.dpk - в открывшемся окне "Package - DsgnCPort7.dpk" жмём кнопку "Compile", потом "Install" - закрываем окно "Package - DsgnCPort7.dpk", но запрос "Сохранить" жмём "Нет" - проверяем на вкладке компонентов наличие вкладки "CPortLib" - все файлы cport которые будет требовать компилятор копируем из cport-3.10\sources\ в C:\Program Files\Borland\Delphi7\Projects\Bpl\, как правило это *.dcu, *.dfm, *.pas, CPort.inc, CPortImg.res вроде всё Изменено 26 сентября, 2016 пользователем dm37 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
paskal 1 28 января, 2019 Опубликовано 28 января, 2019 · Жалоба Добрый день! Пишу программу для асинхронного приема в ком порт. Прием в целом идет успешно, но возникает глюк при смене порта. То есть при асинхронном ожидании приема, порт закрывается, открывается другой, создается новый поток. Ну в общем все действия которые были с предыдущим портом. В этот момент и возникает дефект. Эксперименты и отладка показали что проблема возникла от того что поток висит в несигнальном состоянии после вызова WaitForSingleObject. Из за этого поток не завершается, и по цепочке идут другие ошибки. Итак вопрос. Как можно принудительно завершить ожидание по WaitForSingleObject? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 29 января, 2019 Опубликовано 29 января, 2019 · Жалоба 10 часов назад, paskal сказал: Итак вопрос. Как можно принудительно завершить ожидание по WaitForSingleObject? Заменить WaitForSingleObject на WaitForMultipleObjects. В список ожидаемых объектов добавить свой event, его сигналить при необходимости завершить работу потока. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 228 29 января, 2019 Опубликовано 29 января, 2019 · Жалоба 22 часа назад, paskal сказал: Итак вопрос. Как можно принудительно завершить ожидание по WaitForSingleObject? Послать ему event конечно же. А вы чего ожидали? Ещё можно таймаут установить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
paskal 1 29 января, 2019 Опубликовано 29 января, 2019 · Жалоба 3 hours ago, jcxz said: Послать ему event конечно же. А вы чего ожидали? Ну я и посылал через SetEvent. Ничего не произошло. И я поискал информацию - выходит и не должно. Пока поток спит в WaitForSingleObject, сигнальное состояние нельзя установить. Заколдованный круг. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
paskal 1 29 января, 2019 Опубликовано 29 января, 2019 · Жалоба 15 hours ago, AHTOXA said: Заменить WaitForSingleObject на WaitForMultipleObjects. В список ожидаемых объектов добавить свой event, его сигналить при необходимости завершить работу потока. А можно подробнее как завершать поток с использованием WaitForMultipleObjects ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
V_G 7 30 января, 2019 Опубликовано 30 января, 2019 · Жалоба Я делал из MFC ручками без WaitForMultipleObjects и аналогичных функций: 1. Заводил глобальный указатель на переменную lpvNeedReceive - флаг управления потоком, № Com-порта (инициировал lpvNeedReceive при открытии порта). 2. В потоке приема данных заводил цикл while(*(UINT *)lpvNeedReceive != 0), в котором делаю WaitCommEvent - ожидание одного из событий EV_RXCHAR|EV_TXEMPTY|EV_BREAK. 3. По EV_RXCHAR принимаю информацию обычным образом. 4. Если нужно закрыть порт и приемный поток, в основном потоке делаю *lpvNeedReceive = 0, отправляю в порт ничего не значащий нулевой байт и жду изменения *lpvNeedReceive. 5. Приемный поток выходит из WaitCommEvent и из цикла по п.2, закрывает компорт и в конце своей работы устанавливает *lpvNeedReceive = 0xFF. 6. Основной поток закрывает приемный поток Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 228 30 января, 2019 Опубликовано 30 января, 2019 · Жалоба 10 часов назад, paskal сказал: Ну я и посылал через SetEvent. Ничего не произошло. И я поискал информацию - выходит и не должно. Пока поток спит в WaitForSingleObject, сигнальное состояние нельзя установить. Вы сами то поняли смысл того что написали? По вашему выходит что WaitForSingleObject вообще нельзя использовать. Если поток ждёт event-а в WaitForSingleObject, то естественно он должен переходить в активное состояние после того как кто-то сделает SetEvent для этого объекта. Или истечёт таймаут WaitForSingleObject. Ищите где накосячили. 1 час назад, V_G сказал: отправляю в порт ничего не значащий нулевой байт и жду изменения *lpvNeedReceive. Зачем такие кривые костыли? Достаточно просто установить сигнальное состояние для event-а вручную и всё. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
V_G 7 30 января, 2019 Опубликовано 30 января, 2019 · Жалоба 28 минут назад, jcxz сказал: Зачем такие кривые костыли? Достаточно просто установить сигнальное состояние для event-а вручную и всё. Согласен, но софт компорта писался лет 20 назад (почти сразу же, как появилась многопоточность) и с тех пор особо не менялся, бо работает. Я и сейчас-то не все виндовые функции знаю наизусть, а тогда - и подавно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 30 января, 2019 Опубликовано 30 января, 2019 · Жалоба 10 часов назад, paskal сказал: А можно подробнее как завершать поток с использованием WaitForMultipleObjects ? Создайте ещё один Event: HANDLE terminateEvent = CreateEvent(NULL, FALSE, FALSE, NULL); Замените свой WaitForSingleObject(oldEvent, ...) на HANDLE events[] = {oldEvent, terminateEvent}; WaitForMultipleObjects(2, events,...); И вы сможете в любой момент вывести поток из ожидания, взведя terminateEvent. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 228 30 января, 2019 Опубликовано 30 января, 2019 · Жалоба 24 минуты назад, V_G сказал: Согласен, но софт компорта писался лет 20 назад (почти сразу же, как появилась многопоточность) и с тех пор особо не менялся, бо работает. Я и сейчас-то не все виндовые функции знаю наизусть, а тогда - и подавно. Тоже писалось ровно 10 лет назад, использовалось во множестве проектов: Спойлер // Receiver thread //--------------------------------------------------------------------------- void __fastcall TCommRxThread::Main() { DWORD i, ii, j; do { EnterCriticalSection(&cs); terminate = amount = 0; LeaveCriticalSection(&cs); if (purge) { purge = false; SetEvent(evPurge); } SetEvent(hServiceEvent); while (1) { j = 0; do { ReadFile(hComm, buf + posIObuf + j, bufSize - j, &i, &ovr); if (!terminate) ii = GetOverlappedResult(hComm, &ovr, &i, true); if (terminate) break; if (!ii) { if (OnError) Synchronize(OnError); i = 0; } j += i; } while (!j || (j < bufSize && amount)); WaitForSingleObject(hServiceEvent, INFINITE); if (terminate) break; EnterCriticalSection(&cs); amount = j; posServBuf = posIObuf; posIObuf ^= bufSize; LeaveCriticalSection(&cs); if (OnReady) Synchronize(OnReady); } PurgeComm(hComm, PURGE_RXABORT | PURGE_RXCLEAR); } while (purge); } uint __fastcall TCommRxThread::Read(char *data, uint size) { EnterCriticalSection(&cs); if (size >= amount) { SetEvent(hServiceEvent); size = amount; } memcpy(data, buf + posServBuf, size); posServBuf += size; amount -= size; LeaveCriticalSection(&cs); return size; } void __fastcall TCommRxThread::Purge() { if (terminate) return; purge = true; EnterCriticalSection(&cs); Terminate(); LeaveCriticalSection(&cs); WaitForSingleObject(evPurge, INFINITE); } void __fastcall TCommThread::Terminate() { terminate = true; SetEvent(hServiceEvent); SetEvent(ovr.hEvent); } class TCommRxThread : public TCommThread { ... }; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
klod 0 7 октября, 2022 Опубликовано 7 октября, 2022 · Жалоба Всем добрых суток ! У меня проблема приема данных по СОМ порту. Данные выдаются пакетом из устройства в порт ПК каждые 100 мс размером 2500 байт. Но происходит потеря данных, вернее последовательность данных при чтении буфера порта нарушается, скажем так, последний номер пакета был с номером 2000, а при следующем чтении порта начинается не 2001, а ,например, 2020. Настройка порта следующая: 8 бит; Контроль четности - нет; Число стоп бит - 1; Скорость обмена -460800; Таймауты по умолчанию, кроме MAXWORD все нули. Размер буфера порта 4096, увеличивал до 15000. В программе сначала использовал библиотеку Async32, пробовал делать свой поток с функциями API (ReadFile), тут результат еще хуже, чтение производится, то 14000 байт, то 45 байт, что приводит к потере. Чтение происходит по событию RXchar. Выкладываю код в потоке. procedure MyThread.execute; var S: string; i:integer; begin //inherited; OverRead.hEvent:=CreateEvent(nil,True,True,nil); while not MyThr.Terminated do begin WaitCommEvent(FHandle,Mask,@OverRead); signal:=WaitForSingleObject(OverRead.hEvent,infinite); if(signal=Wait_Object_0) then begin if GetOverlappedResult(FHandle,OverRead,Temp,true) then begin if((Mask and EV_RXchar)<>0) then begin ClearCommError(FHandle,Temp,@ComStat); Btr:=ComStat.cbInQue; if Btr<>0 then begin ReadFile(FHandle,Buffer,SizeOf(Buffer1),Temp,@OverRead); end; end; end; end; Еще один вариант. Использовал библиотеку API для устройств FTDI. Функция в потоке. Function Drive:Boolean; var B:Byte; Sgn,RR,BT : DWORD; CS : TComStat; i:integer; ReadOL : TOverLapped; begin while not FReadThread.Terminated do begin FillChar(ReadOL,SizeOf(ReadOL),0); ReadOL.hEvent:=CreateEvent(nil,True,True,nil); FT_W32_ReadFile(FHandle,B,1,RR,@ReadOL); Sgn:=WaitForSingleObject(ReadOL.hEvent,INFINITE); Result:=False; if (Sgn=WAIT_OBJECT_0) then begin if GetOverlappedResult(FHandle,ReadOL,BT,False) then begin PutS(inp,B); // очередной байт сообщения end; end; FT_W32_CloseHandle(ReadOL.hEvent); end; end; Здесь картина несколько иная. Если читаю в буфер, то прием хоть и фиксированный, но потери такие же как описал выше. А если читаю по одному байту, то читается как надо, но постоянно до определенного момента (около 4000 пакетов принимаются как надо), потом идут потери данных, вероятно буфер драйвера все-же переполняется. Хотелось бы узнать, реально читать данные при такой скорости и настройке без потерь или в Windows это дело гиблое? И есть ли еще инструменты читать данные без потерь? Пожалуйста, помогите, буду признателен за любую помощь Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 228 7 октября, 2022 Опубликовано 7 октября, 2022 · Жалоба У вас какая-то каша в коде... Вызывать нужно ReadFile(), а затем - GetOverlappedResult(). А не наоборот. Советую прочитать описание WinAPI. А всякие WaitCommEvent(), ClearCommError(), WaitForSingleObject() вообще не понятно с какого рожна приплетены? Это же поток читающий символы из UART. Вот это он и должен делать. 1 час назад, klod сказал: И есть ли еще инструменты читать данные без потерь? Инструмент только один: внимательное чтение документации на WinAPI. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 27 7 октября, 2022 Опубликовано 7 октября, 2022 · Жалоба 3 часа назад, klod сказал: . . . . Данные выдаются пакетом из устройства в порт ПК каждые 100 мс размером 2500 байт. Но происходит потеря данных . . . . Скорость обмена -460800; Таймауты по умолчанию, кроме MAXWORD все нули. . . . Хотелось бы узнать, реально читать данные при такой скорости и настройке без потерь или в Windows это дело гиблое? И есть ли еще инструменты читать данные без потерь? Попробуйте поработать с таймаутами, для этого размер буфера поставьте заведомо больше ваших 2500, например 50000, тогда функция будет отрабатывать не по заполнению буфера, а по отработке таймаута (они должны соотв-ть длительности пакета и паузы между ними). Их там (таймаутов) задается 3 (насколько помню). Это работало для небольших скоростей, до 115200. Насколько эффективно это, и будет ли работать для 460800 сказать не могу. Отладьте работу на низкой скорости, затем пробуйте на высокой. Скорость достаточно высокая, но драйвер порта должен обеспечивать получение данных. Вопрос в правильной его настройке и своевременном считывании данных из буфера драйвера. Инфорамция к размышлению: See also SetCommTimeouts function, etc https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setcommtimeouts -------------- COMMTIMEOUTS Communications Functions Communications Resources GetCommTimeouts SetCommTimeouts ReadFile ReadFileEx WriteFile WriteFileEx Структура DCB Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться