Russian Qt Forum
Ноябрь 13, 2024, 09:28 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Прога на ваш суд  (Прочитано 10285 раз)
labview
Гость
« : Август 11, 2010, 21:43 »

Написал первую в жизни прогу с Qt (не без помощи этого форума). Раньше программировал на графическом языке программирования, где всё по-другому. Так что C/C++ я знаю только из далека (когда то в течении полугода программировал микроконтроллеры на си).

Так вот, решил сделать прогу для пробы, в ней задействованы сигналы и слоты, QThread и скачаная мной библиотека QExtSerialPort. Мне очень интересно услышать ваше мнение по поводу качаства программирования, услышать много советов по улучшению. Сама прога представляет из себя терминал для комуникации через последовательный порт (наподобии Windows Hyperterminal).

Для проверки проги потребуются два последовательных порта и один Crossover - кабель для соединения этих двух портов.
На крайняк должно хватить одного порта, тогда нужно соединить пины 2 и 3 и в терминале должно отбображаться эхо, то есть что печатаем, то и видим.

Програ скомпилирована под 7 виндой 64 бит и пентиумом. Все сырцы (включая внешнюю библиотеку) прилагаются.

Спасибо.


http://labviewportal.eu/download/file.php?id=5884

ЗЫ размер вложения не должен превышать 500 КБ, поэтому прогу выложил в своём форуме, а сырцы здесь.
Записан
QCasper
Гость
« Ответ #1 : Август 12, 2010, 00:39 »

И не глючит? На вскидку - в реализации класса, который выполняется в отдельном потоке ни одного объекта синхронизации.
Или может я что-то не так понял... В чём интрига? Улыбающийся
Записан
labview
Гость
« Ответ #2 : Август 12, 2010, 01:05 »

Спасибо за первый отклик.
Не глючит? Это вопрос?

У меня вроде не глючит, тестил недолго и только на двух компах, поэтому попросил потестить вас.

Да, отдельный поток конкретно здесь, в этой проге, в принципе лишний.  В Qt есть встроенный отдельный ивент луп (event loop) и это меня радует. Вообще то, во всех моих рабочих проектах программе приходится общатся параллельно по нескольким интерфейсам, так вот чтобы одно от другого не зависело, я создаю на каждый прибор свой поток. Ну и здесь по привычке для интерфейса сделал свой поток.
Если бы я программировал не на Qt(где как я понял уже есть event loop), мне бы тоже пришлось создавать два потока, чтобы обработка событий и чтение с порта не зависели друг от друга и нажатие на кнопку не зависало.
Ну а вобщем так, для тренировки попробовал использовать QThread, уверен он мне ещё понадобится.

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

Какие способы (обьекты) для синхронизации Вы имели в виду?
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #3 : Август 12, 2010, 08:14 »

2 QCasper
Цитировать
И не глючит? На вскидку - в реализации класса, который выполняется в отдельном потоке ни одного объекта синхронизации.
Или может я что-то не так понял... В чём интрига? Улыбающийся

В принципе не нужны тут никакие объекты синхронизации. Что с чем хотите синхронизировать то? Читает из порта то ведь всегда один поток (run), а пишет в порт  другой (главный).  Тем более, в библиотеке QExtSerialPort (если мне не зменяет память) уже все операции I/O мьютексом разграничены.

2 labview
Цитировать
Так вот, решил сделать прогу для пробы, в ней задействованы сигналы и слоты,
...
Мне очень интересно услышать ваше мнение по поводу качаства программирования, услышать много советов по улучшению. Сама прога представляет из себя терминал для комуникации через последовательный порт (наподобии Windows Hyperterminal).
...
Ну, для этой либы (v 1.2) уже есть GUI терминал (см. qt-apps.org). Поищите.

Цитировать
QThread и скачаная мной библиотека QExtSerialPort.
Либа древняя как Г мамонта. Более новая ее интерпретация тут: http://code.google.com/p/qextserialport/ .
Тем более, если устраивает лицензия GPL - то есть и другая библиотека QSerialDevice, в которой это все реализуется проще и т.п.

Цитировать
Да, отдельный поток конкретно здесь, в этой проге, в принципе лишний.
В принципе, да, поток для этой задачи лишний. Но если в будущем необходимо будет писать что-то другое - то потоки пригодятся.

Цитировать
Если бы я программировал не на Qt(где как я понял уже есть event loop), ...
Для версии библиотеки v 1.2 event loop вам не поможет!

Еще:

1. Вечно в цикле в run проверять на наличие байт в порту - не есть красиво. Для этого есть другие способы.
2. У вас в программе чтение происходит в потоке run, а вот запись - в главном потоке , так что если юзер захочет передать тыщупицот байт данных, то GUI затормозит у вас!

Резюме:
    В принципе, для начала не плохо.


 
Записан

ArchLinux x86_64 / Win10 64 bit
mkv
Гость
« Ответ #4 : Август 12, 2010, 08:59 »

Привет!
по коду, что мне сразу бросается в глаза:

1. в конструкторе SerialThread инициализацию portIsOpen и exitThread можно сделать в списке инициализации и значением true (а не TRUE)... в с++ есть тип bool:
2. this в тех случаях, что у тебя использовать не нужно
3. параметры в функции нужно передавать по ссылке и если они не изменяются по сделать их константными (это вообще относится ко всем переменным которые ты не будешь изменять... так проще читать код)
4. char buff[1024]; старайся избегать фиксированных буферов, вместо этого: QByteArray buff; buff.resize(newBufferSize);
5. port->read(buff, numBytes); а если даных в буфере будет больше 1024?
6. если используешь отдельный тред для работы с ком портом можно использовать блокирующее чтение... msleep будет не нужен... вообще sleep ИМХО это моветон.
7. emit SettingsWidget::stop(); или просто emit stop();
8.  во всех случаях с new: te = new MyTextEdit; лучше явно указать родителя:  te = new MyTextEdit(this);
9. void quit(void); для плюсов void quit();

з.ы. прогу не запускал...
Записан
labview
Гость
« Ответ #5 : Август 12, 2010, 13:29 »

Либа древняя как Г мамонта. Более новая ее интерпретация тут: http://code.google.com/p/qextserialport/ .
Тем более, если устраивает лицензия GPL - то есть и другая библиотека QSerialDevice, в которой это все реализуется проще и т.п.

Спасибо, скачал либу от туда, но ведь версия совпадает (v1.2 beta). Какая новее?

Вообще всем огромное спасибо. Буду потихоньку дальше отвечать/спрашивать.

Вот кстати прога, написаная на LabVIEW меньше чем за пол дня для себя в проф. интересах. Ну и заодно решил выложить её публике:
http://labviewportal.eu/ru/kommunikacija-s-priborami/100-rs232-terminal
« Последнее редактирование: Август 12, 2010, 14:13 от labview » Записан
labview
Гость
« Ответ #6 : Август 12, 2010, 16:07 »

1. Вечно в цикле в run проверять на наличие байт в порту - не есть красиво. Для этого есть другие способы.
2. У вас в программе чтение происходит в потоке run, а вот запись - в главном потоке , так что если юзер захочет передать тыщупицот байт данных, то GUI затормозит у вас!

1. я понимаю что есть другие способы чтения с порта не используя поллинг, а используя таймаут. Но для этого нужно знать протокол передачи данных (например из скольки байт состоит пакет, syncByte и прочее или например terminationChar), а здесь мы имеем дело с неопределённым протоколом.

2. не очень понимаю. У меня запись не происходит в главном потоке. Главный поток инициирует сигнал на запись, а сама запись происходит в event loop потока SerialThread.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #7 : Август 12, 2010, 18:00 »

Цитировать
1. я понимаю что есть другие способы чтения с порта не используя поллинг, а используя таймаут. Но для этого нужно знать протокол передачи данных (например из скольки байт состоит пакет, syncByte и прочее или например terminationChar), а здесь мы имеем дело с неопределённым протоколом.

Нет, есть такая штука, как события от порта. При ее применении незачем постоянно мониторить порт на предмет bytesAvailable().

Цитировать
2. не очень понимаю. У меня запись не происходит в главном потоке. Главный поток инициирует сигнал на запись, а сама запись происходит в event loop потока SerialThread.

Проверьте.
Записан

ArchLinux x86_64 / Win10 64 bit
labview
Гость
« Ответ #8 : Август 12, 2010, 18:12 »

1. мне думаю вполне хватит port->read(buff, numBytes) и значения Timeouts в настройках порта(при условии если знать сколько байт нужно считывать). Но про ивенты порта думаю узнать не помешало бы. Они реализовано в этой библиотеке?

2. даже не знаю как проверить, я думал, что слот это не просто функция класса, которую можно вызвать из другого потока. Ведь обьект port в главном потоке неизвестен, т.к. инстанциирован в SerialThread. Разве у потоков не разделённые области памяти?

Спасибо.
« Последнее редактирование: Август 12, 2010, 18:17 от labview » Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #9 : Август 12, 2010, 20:09 »

Цитировать
мне думаю вполне хватит port->read(buff, numBytes) и значения Timeouts в настройках порта(при условии если знать сколько байт нужно считывать). Но про ивенты порта думаю узнать не помешало бы. Они реализовано в этой библиотеке?

Вы наверное не так поняли... Причем тут read и Timeouts ? Я говорю вам про то что нет смысла в потоке постоянно опрашивать порт на предмет того, пришли или нет в него данные. т.е. код:
Код:
...
                   [b] numBytes = port->bytesAvailable();[/b]
                    if(numBytes >0)
                    {
                        port->read(buff, numBytes);
                        buff[numBytes] = '\0';
                        QString msg = buff;
                        emit this->RX(msg);
                    }
...

не нужен!

В той Qext что на google code есть жалкое подобие. Улыбающийся (QSerialDevice лучше в этом отношении). А хотя, что вам говорить то? Смотрите сами код. Улыбающийся

Цитировать
даже не знаю как проверить, я думал, что слот это не просто функция класса, которую можно вызвать из другого потока. Ведь обьект port в главном потоке неизвестен, т.к. инстанциирован в SerialThread. Разве у потоков не разделённые области памяти?

натыкайте в main(), перед write(), перед read() код типа:
Код:
...
    qDebug() << "Current thread id is: " << QThread::currentThreadId();
...

и увидите, что ID потока main() и при выполнении write() будут совпадать!  Улыбающийся
Записан

ArchLinux x86_64 / Win10 64 bit
labview
Гость
« Ответ #10 : Август 12, 2010, 20:29 »

1. я всё же не согласен с тем что использование ивентив порта конкретно в этой программе принесёт полезность. Я прекрасно понимаю что проверка данных в буфере это поллинг, но ведь у меня есть sleep на 100 мс. Т.е. в случае если данные накопились максимально за 100 мс пока я спал, то считываем и отправляем их все вместе.
В случае с ивентами мы бы получали ивент автоматически, при появлении данных в порте (обычно сразу после первого байта). Но зачем пользователю видеть каждый приходящий байт по их поступлению в порт? Это только загрузит процессор, т.к. комп должен апдейтить окно чаще.
Может быть я что то не понимаю, если можно предложите Ваш вариант с использованием ивентов. Ну или просто опишите словами замену вышестоящего куска кода.

Спасибо!

2. нужно бы проверить, для меня это очень важно!!!
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.115 секунд. Запросов: 23.