Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Проблема с прогой


Автор: F_W 11.12.2004, 11:12
Написал прогу, которая принимает данные из одного сом порта, обрабатывает по формату и передает в другой порт. Но есть один касяк. Когда просто запускаешь её, то она работает как надо. Но нужно, чтобы прием и передача шли все время (т.е. нужно порт все время слушать). Если её циклишь, то вылезает виндозная ошибка, типа программа вызвала ошибку и будет закрыта. Почему такое может происходить???

Автор: bel_nikita 11.12.2004, 12:45
Код в студию! smile
Через оверлапед делаешь?

Автор: F_W 11.12.2004, 13:29
int main(int argc, char* argv[])
{

DCB dcb;
COMMTIMEOUTS ct;
HANDLE port1;
DWORD mask;
DWORD bc;
char buf1[100];


dcb.DCBlength=sizeof(DCB);
BuildCommDCB("baud=9600 parity=N data=8 stop=1",&dcb);
dcb.fNull=TRUE;

ct.ReadIntervalTimeout=10;
ct.ReadTotalTimeoutMultiplier=ct.ReadTotalTimeoutConstant=0;
ct.WriteTotalTimeoutMultiplier=ct.WriteTotalTimeoutConstant=0;

//-----------открываем порт сом1 и считываем

port1=CreateFile("COM1",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);

SetCommState(port1,&dcb);
SetCommTimeouts(port1,&ct);
PurgeComm(port1,PURGE_RXCLEAR);


SetCommMask(port1,EV_RXCHAR);
WaitCommEvent(port1,&mask,NULL);
ReadFile(port1,&buf1,100,&bc,NULL);

CloseHandle(port1);

HANDLE port2;

char *buf_out=buf1;
char *buf_in;


int k=0,i=0, n;
char x1[10],x2[20],*px1,*px2;
char *buffer,*p,*p1;

// ----------------убираем пробелы

buffer=buf1;
p = strtok (buffer," ");
p1 = strtok (NULL," ");

//--------------------------убираем буквы

strupr(p1);
p4 = strchr (p1,'K');
*p4=NULL;
strcat (p1,"00 ");


//-----------------------------заменяем , на .

px1 = &p1[0]; px2 = &x2[0]; n = strlen(p1)+1;
while (k<n)
{
if (*(px1+k)!=',')
{
*(px2+i) = *(px1+k); i++; k++;
}
else
{
*(px2+i) = '.'; k++; i += 1;
}
}

//------------------------------ считываем из файла DOS символ (80)

char* path = "3.txt";
char buf[10];
char* data;
FILE *file;

file = fopen(path, "r");
fgets(buf, 30, file);
data=buf;
fclose(file);


//----------------------------------------- соединяем в конечный результат

strcat(data, x2);
strcat(data, "B \r\n");
cout <<"Read to COM2: " << data;
buf_out=data;

// -----------------------------------------отправляем данные

port2=CreateFile("COM2",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
if (port2=="INVALID_HANDLE_VALUE")
{cout << "Can't Open Port";
else
{


SetCommState(port2,&dcb);
SetCommTimeouts(port2,&ct);
PurgeComm(port2,PURGE_TXCLEAR|PURGE_RXCLEAR);

WriteFile(port2,buf_out,strlen(buf_out),&bc,NULL);
CloseHandle(port2);

}

return 0;
}



В общем на сом1 идет строка: +) 000,0kg
На сом2 нужно отправить: А(русская) 00000.0 B(англ) \r\n (возврат коретки + перевод строки)
На HEX это должно так: 80 20 значение цифр 20 42 20 20 0D 0A

Автор: bel_nikita 11.12.2004, 19:46
F_W
Я бы организовал два треда. Первый, который бы читал ассинхронно данные из порта, второй - записывал в порт.
Сейчас подниму свои исходники...

Автор: cardinal 11.12.2004, 20:26
Цитата(bel_nikita @ 11.12.2004, 18:46)
Я бы организовал два треда.

F_W, а я бы организовал один тред smile

Он будет слушателем. В нем крутиться постоянно цикл (со switch внутри, которые позволяет войти нашему треду в разные режимы; стандартный режим слушания это status = 0) и слушает. Как что-то услышал переключает переменную (создай одну глобальную volatile под именем status) status (switch = 1 например) и по switch'у мы перейдем в режим посылки на другой порт. После посылки switch = 0 и мы опять слушаем.
bel_nikita, такой способ организации ИМХО имеет одно большое преимущество: мы управляем всем тредом одной глобальной volatile переменной. Потом можно даже где-нибудь по нажатию button'а перевести тред в другой режим просто присвоив переменной status другое значение. Точно также можно узнать в любой момент в какой режиме находится наш поток.

Добавлено @ 20:27
Модератор: Название темы должно отражать ее суть!

Автор: Goldberg 11.12.2004, 22:10
2 F W
Т.е. у тебя ReadFile(port1,&buf1,100,&bc,NULL); - находится в цикле?
Добавлено @ 22:15
Строка которую ты читаешь, всегда одного размера?

Автор: bel_nikita 13.12.2004, 00:21
cardinal
Позволю не согласиться с тобой smile Будет мега универсальный тред. Получается три в одном. Например, если асинхронное чтение/запись в порт. Что тогда получится? Да и тем более работаем с разными портами. Каждый кусок кода должен выполнять одну четко определенную задачу. Ну, не мне тебя учить smile
Видение реализации задачи, ИМХО: Полнофункциональный класс для работы с портом. Создал два объекта. Потокобезопасный буффер, можно за основу STL контейнер какой-нить. Создал бы два треда. Один эвент(событие), можно с автосбросом. Один тред на просшлушке, второй в ожидании на событие. Тред, который слушает порт, читает данные и кладет их в буффер и кидает событие(евент). Второй тред(который пишет в порт), находится в ожидании события. И как только он получил событие, читает буфер, делает нужные преобразования прочтенных данных и пишет в порт. Второй тред, в это время читает следующую порцию данных. Т.е. более эфективное управление ресурсами получаем.
Конечно, можно сказать, а нафига ж так сложно? smile Но для меня так логичнее. И с раширяемостью проблем в дальнешем не должно возникнуть. А как показывает практика, вносить изменения в код придется. А что делают, треды в данный момент и знать не надо. Все свамо по себе крутиться smile
В общем, можно долго философствовать, но человеку от этого не легче.

F_W
а что за ошибка(конкретнее)? можно на цикл взглянуть?

Автор: cardinal 13.12.2004, 01:08
Цитата(bel_nikita @ 12.12.2004, 23:21)
Второй тред, в это время читает следующую порцию данных. Т.е. более эфективное управление ресурсами получаем.

Это единственная логическая ошибка в твоем рассуждении smile

Процессор у тебя один и одновременно ничего происходить не может. Соответственно "в это время" происходить ничего не будет...

Остается только вопрос
Цитата(bel_nikita @ 12.12.2004, 23:21)
а нафига ж так сложно?

smile

Автор: bel_nikita 13.12.2004, 01:32
cardinal
Цитата
Процессор у тебя один и одновременно ничего происходить не может. Соответственно "в это время" происходить ничего не будет...
smile
Так и знал. Хотел же вставить строчки, что реального рапараллеливания не будет, но решил все же не стоит, ведь пишу пост на профи форум smile
Как раз ошибки нет. Потоки, да и вцелом многозадачность, нужны для эфективного распределения и управление ресурсами. Что в данном случае мы и получаем smile
В примере возможной реализации, который я привел, второй ресурс не простаивает, во время обработки/работы первого. Идет постоянное переключение между процесами, тредами и т.д. Т.е. для каждого треда выделяется кванты времени. В итоге мы получаем "распараллеливание". Хотя реально, физически, на однопроцессорной системе его нет. Есть один БОЛЬШОЙ плюс - эфективное управление ресурсами! Вот, смотри. На ком порт непрерывно, постоянно идут данные. Как в таком случае отправлять данные? Т.е. мы не эффективно используем ресурсы. Мы только принимаем, принимаем и принимаем, а второй ресурс у нас простаивает. А при "распараллеливании" мы уже сможем отправлять данные. Т.к. будет постоянное переключение между тредами. Т.е. эффективность. ЧТД ( что и требовалось доказать ) smile

З.Ы.: вроде более-менее понятно написал smile

Автор: cardinal 13.12.2004, 16:46
Цитата(bel_nikita @ 13.12.2004, 00:32)
Есть один БОЛЬШОЙ плюс - эфективное управление ресурсами!

Какое же оно эффективное?
Цитата(bel_nikita @ 13.12.2004, 00:32)
Т.к. будет постоянное переключение между тредами.

А это вообще-то тоже время занимает -> то есть жрет наши ресурсы.

Если сделать как я предложил, то процесс "принял-послал" будет работать быстрее. smile

Автор: bel_nikita 13.12.2004, 21:37
Ну-ну... smile

Автор: cardinal 14.12.2004, 00:01
А поподробней? smile

Автор: F_W 14.12.2004, 07:54
Получается, что начиная с readfile и до конца нужно поместить в цикл. Но проблема заключается в обработке строки. Без обработки програ ведет себя нормально. А так вызывает ошибку, в которой говорится, что прога будет закрыта, без объяснений. Строка считывается всегда одного формата. + ко всему когда хоть какой-нибудь код ставишь после readfile, то прога начинает принимать с ошибками (это выражается в деформации формата строки).

Автор: En_t_end 14.12.2004, 08:03
bel_nikita
Ты совершенно прав...
Если делать, по методу cardinal'а, то возможно на несколько кб. виртуальной памяти ты получишь выгоду, но проц. будет работать в усиленном режиме.
Наверно не в тему:
Но вот пример, когда лучше организовать два треда, привёл первое попавшееся в мозг...
long int a = 9999999; //глобальные переменные обьявленные в двух //критических точках
long int b = 9999999;
также файл ofstream out;
UINT My_thread(LPVOID pParam)
{ //везде надо делать операции, как с крит. точками...!
for(; a > 0; a--)
{
b++;
return 0; // еслит перед возвращением поставить таймер, результат которого можно с легкость вывести, то можно определить время выполнения потока...
}
}
UINT My_two(LPVOID pParam)
{
while(проверяем живёт ли поток My_thread)
{
out << a; //если правильно всё сделать с крит. точками, то в переменные должны ассинхронно падать данные из первого потока(оба потока обсалютно паралельны)
out << b;
}
return 0;
}
Теперь сверяем таймер и время последнего изменения файла...
Запоминаем результат...
А теперь вот такой код:
....
for(; a > 0; a--)
{
out << a;
b++;
out << b;
}
.......
Соответсвенно измеряем время выполнения оперции, сравниваем результаты, и радуемся smile --- также во втором случае будет усиленная работа проца...
Два треда - лучший выход в данной ситуации... а если бы все так думали, как cardinal , то у процесса system в НТ было бы всего два паралельных потока, а их у него минимум 41... smile...

Автор: cardinal 14.12.2004, 13:35
En_t_end, я уж думал как провести эксперимент с двумя com-портами, но теперь у меня есть твой код и как-нибудь на выходных я с ним поковыряюсь smile
Своей неправоты я не исключаю, но пока отсаюсь при первоначальном мнении smile
Цитата(En_t_end @ 14.12.2004, 07:03)
Два треда - лучший выход в данной ситуации... а если бы все так думали, как cardinal , то у процесса system в НТ было бы всего два паралельных потока, а их у него минимум 41...

Ну ты сказал... Еще бы сказал, что если бы все думали как я, то windows был бы dos'ом. smile

Автор: En_t_end 14.12.2004, 16:19
"поковыряюсь..."
Да кстати в MFC есть класс ассинхронной работы с com...

"Ну ты сказал... Еще бы сказал, что если бы все думали как я, то windows был бы dos'ом."
Нет я имел в виду, что способ : получил-отправил, организованный в одном потоке, также мог быть использованн в НТ-ях, но представь себе, что несколько сервисов(20-30) будут организованны в виде цикла, и только после прохождения всего цикла система получит результат необходимых элементов : очень медленно, + цикл будет использовать туеву тучу проц. времени...

Автор: cardinal 14.12.2004, 18:57
Цитата(En_t_end @ 14.12.2004, 15:19)
представь себе, что несколько сервисов(20-30) будут организованны в виде цикла, и только после прохождения всего цикла система получит результат необходимых элементов : очень медленно, + цикл будет использовать туеву тучу проц. времени...

Ну мы в данном случае обсуждаем ИМХО немного другую ситуацию...

Автор: En_t_end 14.12.2004, 19:56
"Ну мы в данном случае обсуждаем ИМХО немного другую ситуацию..."
Ну дык я поясняю свою оффтопную фразу smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)