Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Синхронизация потоков сomport чтение/запись, Синхронизация потоков 
:(
    Опции темы
zaytsewa
Дата 13.1.2011, 14:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 9.4.2009

Репутация: нет
Всего: нет



Всем привет!
Надо реализовать асинхронную работу с компортом.

Сделала 2 потока: на чтение и на запись ( с определённым интервалом закидываю данные в порт)
Если запускать один поток - он работает - всё ок
Если запускать вместе - то работает только тот, которого первым запустили
Второму времени видимо не выделяется
sleep в потоках не помогает
с мьютексами тоже ничего не получилось(
попробовала поставить приоритеты - тоже ноль реакции

что посоветуете? как выделять потоку квант времени на выполнение?

впринципе можно запись и в главном потоке реализовать, чтобы огород не городить... но пока не хочется



Это сообщение отредактировал(а) zaytsewa - 13.1.2011, 14:05
PM MAIL   Вверх
Dreamer_0x01
Дата 13.1.2011, 15:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: нет
Всего: 12



zaytsewa, 

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

Кроме того, не забывайте, что win-api функции чтения из ком-порта без корректной установки таймаутов способны завесить все, всяк и всячески. Если у вас один из потоков ждет чтения, а данные не приходят, то есть вариант бесконечного нахождения в этом состоянии. Разумеется, если таймауты не выставлены. Если выставлены, то все нормально будет.

Добавлено через 3 минуты и 5 секунд
Цитата(zaytsewa @  13.1.2011,  14:05 Найти цитируемый пост)
что посоветуете? как выделять потоку квант времени на выполнение?

Выделить никак, а принудительно отдать другому - Sleep(0).

Это сообщение отредактировал(а) Dreamer_0x01 - 13.1.2011, 16:00


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
zaytsewa
Дата 13.1.2011, 21:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 9.4.2009

Репутация: нет
Всего: нет



вот основной код

Код

int ComPort::open()
{
 std::wstringstream portNameStream;
 portNameStream << "COM" << _num;
 lpOverlapped = new OVERLAPPED();
 //создать сигнальный объект-событие для асинхронных операций
 lpOverlapped->hEvent = CreateEvent(NULL, true, true, NULL);
   
 _handle = CreateFile(portNameStream.str().c_str(), GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING |FILE_FLAG_OVERLAPPED, NULL);
 if (_handle == INVALID_HANDLE_VALUE) return -1;

 DWORD dwThreadId;
 DWORD fileSize;
 DWORD dwThreadId1;
 DWORD fileSize1;

 data d;
 d.h = _handle;
 d.lpOvl = lpOverlapped;

 readingThread = CreateThread(NULL,
     0,  // размер стека по умолчанию
     (LPTHREAD_START_ROUTINE) ComPort::reading(reinterpret_cast<LPVOID>(&d)),
     (LPVOID) &fileSize,
     0,  // выполнение немедленно
     &dwThreadId);

 writingThread = CreateThread(NULL,
     0,  // размер стека по умолчанию
     (LPTHREAD_START_ROUTINE) ComPort::writing(reinterpret_cast<LPVOID>(&d)),
     (LPVOID) &fileSize1,
     0,  // выполнение немедленно
     &dwThreadId1);

 SetThreadPriority(readingThread, THREAD_PRIORITY_LOWEST);
 SetThreadPriority(writingThread, THREAD_PRIORITY_NORMAL);
}

DWORD WINAPI ComPort::writing(LPVOID lpParam)
{
    data* d = reinterpret_cast<data*>(lpParam);
    HANDLE handle = d->h;
    LPOVERLAPPED lpOvl = d->lpOvl;
    while (1)
    {
        Sleep(100);
        char message[14];
        strcpy(message,"aefwe");
        DWORD bc = 0;
        WriteFile(handle, message, 14, & bc, lpOvl);//) return -1;
        Sleep(10);
    }
}

DWORD WINAPI ComPort::reading(LPVOID lpParam)
{
    data* d = reinterpret_cast<data*>(lpParam);
    HANDLE handle = d->h;
    LPOVERLAPPED lpOvl = d->lpOvl;
    LPVOID bufrd; 
    DWORD mask;
    SetCommMask(handle,EV_RXCHAR);
    while (1)
    {
        Sleep(10);
        WaitCommEvent(handle, &mask, lpOvl);
        int signal = WaitForSingleObject(lpOvl->hEvent, INFINITE);    //приостановить поток до прихода байта
        if(signal == WAIT_OBJECT_0)                        //если событие прихода байта произошло
        {
            DWORD temp;
            GetOverlappedResult(handle, lpOvl, &temp, true);
            printf("temp = %d",temp);
            switch (mask)
            {
                case EV_BREAK:    break;//Во время ввода данных было обнаружено прерывание.
                case EV_CTS:    break;//Сигнал готовности к приему (CTS) изменил состояние.
                case EV_DSR:    break;//Сигнал готовности модема (DSR) изменил состояние.
                case EV_ERR:    break;//Произошла ошибка состояния линии. Ошибкой состояния линии являются CE_FRAME, CE_OVERRUN и CE_RXPARITY.
                case EV_RING:    break;//Был обнаружен индикатор вызова.
                case EV_RLSD:   break;//Сигнал RLSD (детектор принимаемого линейного сигнала) изменил состояние.
                case EV_RXCHAR:    {  //Символ был принят и помещен в буфер ввода данных.
                                    DWORD bc = 0;
                                    char* Buff = new char[temp];
                                    bool Ret = ReadFile(handle, Buff, temp, & bc, lpOvl);
                                    printf("Buff = %s",Buff);
                                    PurgeComm(handle, PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_RXABORT);
                                    //ReleaseMutex(mutex);
                                };break;
                case EV_RXFLAG:    break;//Символ события был принят и помещен в буфер ввода данных. Символ события определяется  в структуре DCB устройства, которое обращается к последовательному порту, используя функцию SetCommState.
                case EV_TXEMPTY: break;
            }
        }
    }
}


настройки:
Код

void Settings::init_dcb()
{
    if (_dcb == NULL) return;
    setByteSize( 8 );
    setParity( false, NO_PARITY );
    setStopBits( TWOSTBITS );
    setBaud( 9600 );
    setOutxCtsFlow( false );
    setOutxDsrFlow( false );
    setDtrControl( DTR_CTRL_DISABLE );
    setRtsControl( RTS_CTRL_DISABLE );
    setDsrSensitivity( false );
    COMMTIMEOUTS ct;
    ct.ReadIntervalTimeout         =            200;
    ct.ReadTotalTimeoutMultiplier  =          40000 / 9600;
    ct.ReadTotalTimeoutConstant    =           200;
    ct.WriteTotalTimeoutMultiplier =             0;
    ct.WriteTotalTimeoutConstant =               0;
    setTimeouts(&ct);
}

PM MAIL   Вверх
xvr
Дата 14.1.2011, 13:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 40
Всего: 223



Нельзя использовать одну и ту же OVERLAPPED структуру в обоих вызовах (FileRead & FileWrite) одновременно.

Да и вообще использование OVERLAPPED IO в 2х потоках - это бред. OVERLAPPED для того и делалась, что бы можно было обходится без потоков.  smile 

PM MAIL   Вверх
zaytsewa
Дата 14.1.2011, 16:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 9.4.2009

Репутация: нет
Всего: нет



Цитата

  OVERLAPPED для того и делалась, что бы можно было обходится без потоков. 


т.е. можно прямо в рабочем потоке сделать цикл while и ждать прихода данных?
а писать в поток можно в любой момент времени?
как узнать занят порт или свободен? надо ли использовать какие-то средства синхронизации?

в OVERLAPPED кроме события ничего интересного не нашла, причём событие не пойми чего...
просто любого изменения порта?

была бы признательна, если бы вы мне всё объяснили или пример привели или ссылку кинули, где всё толково расписано
PM MAIL   Вверх
xvr
Дата 14.1.2011, 18:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 40
Всего: 223



Цитата(zaytsewa @ 14.1.2011,  16:42)
т.е. можно прямо в рабочем потоке сделать цикл while и ждать прихода данных?

Уберите флаг OVERLAPPED из открытия файла и параметр Overlapped из Read/WriteFile. Потом просто в потоке зовете ReadFile и он блокируется, пока не будет прочтенных данных

Цитата

а писать в поток можно в любой момент времени?
В порт в смысле? Да (но из другого потока)

Цитата

как узнать занят порт или свободен? надо ли использовать какие-то средства синхронизации?
Кем занят? Если вами же - то можете писать или  читать хоть в 3 горла, если другими - то вам не дадут его открыть (CreateFile)

Цитата

в OVERLAPPED кроме события ничего интересного не нашла, причём событие не пойми чего...
просто любого изменения порта?
В OVERLAPPED лежит событие, которое взводится когда операция (куда этот OVERLAPPED передавали) реально закончится. При этом сам вызов функции (той же ReadFile к примеру) вернется немедленно (со специальной 'ошибкой')

Цитата

была бы признательна, если бы вы мне всё объяснили или пример привели или ссылку кинули, где всё толково расписано
Вот тут расписанно

PM MAIL   Вверх
zaytsewa
Дата 16.1.2011, 01:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 9.4.2009

Репутация: нет
Всего: нет



Цитата

Кем занят? Если вами же - то можете писать или  читать хоть в 3 горла, если другими - то вам не дадут его открыть (CreateFile)


т.е. можно в одно и то же время писать и читать?? мне почему-то казалось, что можно делать что-то одно в один момент врмемени


за ссылку спасибо)
PM MAIL   Вверх
xvr
Дата 17.1.2011, 10:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 40
Всего: 223



Цитата(zaytsewa @  16.1.2011,  01:41 Найти цитируемый пост)
т.е. можно в одно и то же время писать и читать?? 
IMHO можно.


PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0536 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.