crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

2 страниц V   1 2 >  
Ответить в данную темуНачать новую тему
zuze
  опции профиля:
сообщение 4.11.2012, 17:26
Сообщение #1


Участник
**

Группа: Участник
Сообщений: 211
Регистрация: 4.11.2012
Пользователь №: 3589

Спасибо сказали: 0 раз(а)




Репутация:   0  


Пожалуйста помогите мне с вопросами связанные с программой состоящей из двух потоков.

Описание:
Программа создаёт окно в котором три кнопки.
Первая кнопка запускает и останавливает поток "А".
Вторая кнопка запускает и останавливает поток "В".
Третья кнопка выход из программы.
Поток "А" печатает символ "А".
Поток "В" печатает символ "В".

Создал проект и в нём сделал 5 файлов с кодом:
1. main.cpp
2. thread.cpp
3. thread.h
4. threaddialog.cpp
5. threaddialog.h

Файл main.cpp

#include <QApplication>
#include "threaddialog.h"
 
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    ThreadDialog dialog;
    dialog.show();
    return app.exec();
}


Файл thread.cpp

#include <QtCore>
#include <iostream>
using namespace std;
#include "thread.h"
 
// Описание конструктора
Thread::Thread()
{
  stopped = false;
}
// Вывод потока
void Thread::setMessage(const QString &message)
{
    messageStr = message;
}
// Запуск потока
void Thread::run()
{
  while (!stopped)
    cerr << qPrintable(messageStr);
  stopped = false;
  cerr << endl;
}
// Остановка потока
void Thread::stop()
{
  stopped = true;
}


Файл thread.h

#ifndef THREAD_H    // Обявление заголовочного файла
#define THREAD_H    // Обявление заголовочного файла
 
#include <QThread>  // Объявление родительского класса
 
class Thread : public QThread
{
    Q_OBJECT
public:
  Thread(); // Прототип конструктора (определённая функция)
 
  void setMessage(const QString &message); // Прототип функции вывода на экран значений потока
  void run();   // Прототип функции запуска потока
  void stop();  // Прототип функции остановки потока
 
private:
  QString messageStr;
  volatile bool stopped;    // Флаг указывающий потоку запуститься или остановиться
};
#endif // THREAD_H // Обявление заголовочного файла


Файл threaddialog.cpp

#include <QtGui>
#include "threaddialog.h"
 
ThreadDialog::ThreadDialog(QWidget *parent) : QDialog(parent)
{
    threadA.setMessage("A");
    threadB.setMessage("B");
 
    threadAButton = new QPushButton(tr("Start A"));
    threadBButton = new QPushButton(tr("Start B"));
    quitButton = new QPushButton(tr("Quit"));
    quitButton->setDefault(true);
 
    connect(threadAButton, SIGNAL(clicked()), this, SLOT(startOrStopThreadA()));
    connect(threadBButton, SIGNAL(clicked()), this, SLOT(startOrStopThreadB()));
    connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
 
    QHBoxLayout *mainLayout = new QHBoxLayout;
    mainLayout->addWidget(threadAButton);
    mainLayout->addWidget(threadBButton);
    mainLayout->addWidget(quitButton);
    setLayout(mainLayout);
 
    setWindowTitle(tr("Threads"));
}
 
void ThreadDialog::startOrStopThreadA()
{
    if (threadA.isRunning())
    {
        threadA.stop();
        threadAButton->setText(tr("Start A"));
    }
    else
    {
        threadA.start();
        threadAButton->setText(tr("Stop A"));
    }
}
 
void ThreadDialog::startOrStopThreadB()
{
    if (threadB.isRunning())
    {
        threadB.stop();
        threadBButton->setText(tr("Start B"));
    }
    else
    {
        threadB.start();
        threadBButton->setText(tr("Stop B"));
    }
}


Файл threaddialog.h

#ifndef THREADDIALOG_H
#define THREADDIALOG_H
#include <QDialog>
#include "thread.h"
 
class QPushButton;
 
class ThreadDialog : public QDialog
{
    Q_OBJECT
public:
    ThreadDialog(QWidget *parent = 0);
 
protected:
    void closeEvent(QCloseEvent *event);
 
private slots:
    void startOrStopThreadA();
    void startOrStopThreadB();
 
private:
    Thread threadA;
    Thread threadB;
    QPushButton *threadAButton;
    QPushButton *threadBButton;
    QPushButton *quitButton;
};
#endif // THREADDIALOG_H


1. В "Nokia Qt SDK Win online v1.0.2 (2010)" при запуске терминала выдаётся ошибка "Failed to read env file: No error".
2. В "Nokia Qt SDK Win offline v1.2.1 (2012)" Данные потоков почему-то выводятся в окне "Вывод приложения", аналог окна "Консоль приложения" в старых версиях.
Если, запускаешь два потока очень быстро подвисает Qt Creator. Если запускаешь терминал выдаётся ошибка "Failed to read env file: No error".

Вопросы:
1. Почему в "Nokia Qt SDK Win online v1.0.2 (2010)" не выводятся результаты потоков и как это поправить?
2. Правильно ли что в "Nokia Qt SDK Win offline v1.2.1 (2012)" результаты потоков выводятся в окне "Вывод приложения", а не в терминале?
3. Подвисает Qt Creator после запуска двух потоков это следствие того что я в программе не сделал синхронизацию потоков?
4. Если есть ещё какие-то нюансы которые я не заметил, напишите пожалуйста?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
RazrFalcon
  опции профиля:
сообщение 4.11.2012, 18:35
Сообщение #2


Zombie Mod
*****

Группа: Участник
Сообщений: 1654
Регистрация: 24.5.2010
Из: Харьков
Пользователь №: 1752

Спасибо сказали: 64 раз(а)




Репутация:   212  


Повисает скорее всего потому что это винда, а вы пытаетесь на всех парах выводить строку.
И судя по коду, она будет выводится очень быстро, из-за чего qt creator повиснет.
На лине такого не будет, в силу особенностей реализации.

Что бы не повисало - попробуйте выводить текст по таймеру, к примеру, каждые 100мс и тп.

Как вариант, попробуйте вместо cerr - qDebug(). Тогда больше вероятность появления текста в консоли.

И лучше создавать потоки нестатичными.
threadA = new Thread(this);
threadB = new Thread(this);
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
zuze
  опции профиля:
сообщение 4.11.2012, 19:13
Сообщение #3


Участник
**

Группа: Участник
Сообщений: 211
Регистрация: 4.11.2012
Пользователь №: 3589

Спасибо сказали: 0 раз(а)




Репутация:   0  


RazrFalcon, попробовал cerr заменить на qDebug(). Результат этого такой в "Nokia Qt SDK Win offline v1.2.1 (2012)" ничего не изменилось, а в "Nokia Qt SDK Win online v1.0.2 (2010)" данные потока начали выводиться в окне "Консоль приложения". Но вроде это окно совершенно для других целей, а не для вывода результатов программы. Что ещё можно сделать или окно "Консоль приложения" это третий вариант вывода данных программы в Qt?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 4.11.2012, 21:22
Сообщение #4


Профессионал
*****

Группа: Модератор
Сообщений: 1611
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 219 раз(а)




Репутация:   12  


многопоточная безопасность при синхронизации стандартных потоков ввода-вывода гаратирована только в стандарте C++11. я не знаю, поддерживает ли компилятор для Nokia в этом примере стандарт С++11.
в прочих реализациях конкуренция потоков за вывод данных может приводить к нарушениям памяти.

Сообщение отредактировал Iron Bug - 4.11.2012, 21:26
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
zuze
  опции профиля:
сообщение 4.11.2012, 22:36
Сообщение #5


Участник
**

Группа: Участник
Сообщений: 211
Регистрация: 4.11.2012
Пользователь №: 3589

Спасибо сказали: 0 раз(а)




Репутация:   0  


Может что не выводиться в терминале виноват мой файл проекта в который я что-то не вписал?

Файл проекта Project3.pro

SOURCES += \
    main.cpp \
    thread.cpp \
    threaddialog.cpp

HEADERS += \
    thread.h \
    threaddialog.h


На всякий случай хочу сказать, что я сижу под Microsoft Windows 7 x64.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
zuze
  опции профиля:
сообщение 5.11.2012, 9:11
Сообщение #6


Участник
**

Группа: Участник
Сообщений: 211
Регистрация: 4.11.2012
Пользователь №: 3589

Спасибо сказали: 0 раз(а)




Репутация:   0  


Я попробовал сделать так, на примере программы которая выводятся только строка текстовая "Hello":

Настройка:
1. "Убрал галочку возле пункта "Запускать в терминале" не подходит.
2. Слева в Qt Creator нажал "Проекты->Собрать->Среда сборки->Подробнее и поставил галочку возле "Чистая системная среда".

Результат такой:
1. Если выполнил только первую настройку, то в терминале высвечивается "Failed to read env file: No error".
2. Если выполняю только вторую настройку, то в терминал не появляется, а "Hello" выводится в окне "Вывод приложения" и когда я пытаюсь закрыть окно "Вывод приложения" меня предупреждают, что программа ещё почему-то выполняется.
3. Если выполнил обе настройки, то терминал выводиться пустым и в окне "Вывод приложения" результат не появляется.

Значит и для моей программы с потоками эти настройки не помогут, а жаль.

Цитата(zuze @ 5.11.2012, 9:09) *
1. "Убрал галочку возле пункта "Запускать в терминале" не подходит.


Не "Убрал", а "Поставил".
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 5.11.2012, 16:13
Сообщение #7


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(Iron Bug @ 4.11.2012, 23:22) *
конкуренция потоков за вывод данных может приводить к нарушениям памяти.
zuze, другими словами - обычно меняют некую переменную из разных потоков, а в основном потоке (и единственном) выводят эту переменную на экран.


Цитата(zuze @ 4.11.2012, 21:13) *
Что ещё можно сделать или окно "Консоль приложения" это третий вариант вывода данных программы в Qt?
я почти не пользуюсь Креатором, но в первых версиях у него была настройка - "объединять потоки stdout и stderr", если они объеденены, то то всё что в эти потоки отправляется будет видно в одном и том же месте.
А вот выводить ли в отдельно открывающуюся консоль или внутри Креатора, зависит от состояния упомянутой тобой галочки:
Цитата(zuze @ 5.11.2012, 11:11) *
"Запускать в терминале"

Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
zuze
  опции профиля:
сообщение 5.11.2012, 16:49
Сообщение #8


Участник
**

Группа: Участник
Сообщений: 211
Регистрация: 4.11.2012
Пользователь №: 3589

Спасибо сказали: 0 раз(а)




Репутация:   0  


Litkevich Yuriy, большое спасибо! Теперь я понял, что данные программы могут выводиться, помимо графически и терминала, также в самом Qt Creator и это не ошибка. Для меня это ново, так как в других средах программирования такого не было. Данную среду программирования я только недавно начал изучать.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 5.11.2012, 16:57
Сообщение #9


фрилансер
******

Группа: Участник
Сообщений: 2943
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


zuze, это всё следует из стандартных потоков ввода-вывода - когда запускаешь дочерний процесс, можно перехватить его поток вывода
http://ru.wikipedia.org/wiki/%D0%A4%D0%B0%...B5_%D0%A1%D0%B8
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
zuze
  опции профиля:
сообщение 5.11.2012, 18:46
Сообщение #10


Участник
**

Группа: Участник
Сообщений: 211
Регистрация: 4.11.2012
Пользователь №: 3589

Спасибо сказали: 0 раз(а)




Репутация:   0  


Алексей1153, большое спасибо за статью. Буду со всем этим разбираться. Я только написал программу по нажатию на кнопку выскакивала надпись "Hello World!" и мне сказали сразу пиши уже процессы. Хорошо что я их немного на gcc писал. Так что у меня поначалу могут возникать совсем детские вопросы, так как в этой среде программирования новичок.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

2 страниц V   1 2 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0


RSS Рейтинг@Mail.ru Текстовая версия Сейчас: 3.5.2025, 16:34