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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: QThread&QProcess  (Прочитано 6035 раз)
Az
Гость
« : Май 01, 2010, 22:08 »

Всем привет.
Коллеги, можно попросить вас самый элементарный пример запуска процесса (например любой команды консоли) в отдельном потоке, GUI приложения? Хотя бы в общих чертах.
Для понимания, связи с чем возник вопрос:
Есть приложение, у которой есть 2 чекбокса, один - lsof, второй - strace. Еще есть textEdit, в которую читается вывод команд и кнопка запуска.
Смысл в том, чтобы можно было одновременно запустить и strace и lsof, в 2 разных потоках.
Насколько я понял, нужно создавать отдельный слот для вывода из потоков в основной?
Записан
Az
Гость
« Ответ #1 : Май 01, 2010, 23:23 »

Начал по-тихоньку писать, исходя из найденных кусков кода и страниц ассистента.

mainwindow.cpp

Код
C++ (Qt)
#include "mainwindow.h"
#include "ui_mainwindow.h"
 
MainWindow::MainWindow(QWidget *parent)
   : QMainWindow(parent), ui(new Ui::MainWindow)
{
       ui->setupUi(this);
}
 
MainWindow::~MainWindow()
{
   delete ui;
}
 
 
void MainWindow::on_pushButton_clicked()
{
   ServerThread th;
   th.start();
}

mainwindow.h

Код
C++ (Qt)
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
 
#include <QtGui/QMainWindow>
#include <QProcess>
#include <QString>
#include "thread.h"
 
namespace Ui
{
   class MainWindow;
}
 
class MainWindow : public QMainWindow
{
   Q_OBJECT
 
public:
   MainWindow(QWidget *parent = 0);
   ~MainWindow();
 
private:
   Ui::MainWindow *ui;
 
private slots:
   void on_pushButton_clicked();
};
 
#endif // MAINWINDOW_H

thread.cpp
Код
C++ (Qt)
#include "thread.h"
#include "mainwindow.h"
#include <QProcess>
#include <QTextCodec>
#include <QDebug>
 
void ServerThread::run()
{
   process = new QProcess(this);
   process->setProcessChannelMode(QProcess::MergedChannels);
   connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(output()));
   process->start("uname");
   exec();
}
void ServerThread::output()
{
   QByteArray bytes = process->readAllStandardOutput();     //как передать вывод из созданного потока в основной?
}
 

thread.h
Код
C++ (Qt)
#ifndef THREAD_H
#define THREAD_H
#include <QThread>
 
class QProcess;
 
class ServerThread : public QThread
{
   Q_OBJECT
 
public:
    void run();
 
public slots:
    void output();
 
signals:
 
private:
   QProcess *process;
 
};
 
#endif // THREAD_H

Хочу пока просто вывести вывод команды uname в отдельном потоке.
Но не совсем пойму, как именно делать вывод из созданного потока в основной.
На данный момент при попытке компиляции, программа вылетает. Если трассировать вручную, то отладчик пишет:
Код:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is ServerThread(0xbfffd8c4), parent's thread is QThread(0x804f818), current thread is ServerThread(0xbfffd8c4)
QThread: Destroyed while thread is still running
Записан
spectre71
Гость
« Ответ #2 : Май 02, 2010, 10:25 »

Хочу пока просто вывести вывод команды uname в отдельном потоке.
Но не совсем пойму, как именно делать вывод из созданного потока в основной.
На данный момент при попытке компиляции, программа вылетает. Если трассировать вручную, то отладчик пишет:
Код:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is ServerThread(0xbfffd8c4), parent's thread is QThread(0x804f818), current thread is ServerThread(0xbfffd8c4)
QThread: Destroyed while thread is still running

Все правильно, нелязя создать дочерний QObject от родителя из друргого потока.
ServerThread - родитель, создавался в главном потоке и живет в нем, а
process - содается в другом потоке => не может быть ребенком ServerThread (process = new QProcess(this);)

Можешь сделать так:

Код
C++ (Qt)
void ServerThread::run()
{
   QProcess process;
   process.setProcessChannelMode(QProcess::MergedChannels);
   connect(&process, SIGNAL(readyReadStandardOutput()), this, SLOT(output()));
   process.start("uname");
   exec();
}
 

Записан
Az
Гость
« Ответ #3 : Май 02, 2010, 13:31 »

А, так вот оно в чем проблема была. Понял.
Спасибо тебе, друг!
Записан
Marat(Qt)
Гость
« Ответ #4 : Май 02, 2010, 15:42 »

Я думаю понятно, что QProcess не должна быть локальной переменной. А работу с QProcess необязательно в отдельный тред выносить. Просто делаешь process.start в основном потоке и все. Т.к. процесс(например strace) - отдельная программа, то и выполняется он операционной системой как отдельная программа, т.е. QProcess::start не вешает gui.
Записан
Az
Гость
« Ответ #5 : Май 02, 2010, 17:37 »

Я думаю понятно, что QProcess не должна быть локальной переменной. А работу с QProcess необязательно в отдельный тред выносить. Просто делаешь process.start в основном потоке и все. Т.к. процесс(например strace) - отдельная программа, то и выполняется он операционной системой как отдельная программа, т.е. QProcess::start не вешает gui.

Если бы вывод был только strace, то да, но основнаяа задача - одновременный запуск strace и lsof, и мне кажется, что их выполнение в одном потоке приведет к вылету, как и случается, если дать обе команды одновременно в терминале.
Исходя из этого, я и подумал, что лучше наверное создавать для каждого свой поток.

Застрял тут я с выводом данных из дочернего потока:
Если в ф-цию output добавить:
Код
C++ (Qt)
emit updateOutput(bytes);
предварительно объявив сигнал в классе thread.
И попробовать выводить данные как-нибудь так:
Код
C++ (Qt)
connect(&th,SIGNAL(updateOutput(QString)),this,SLOT(setOutput(QString)));
где setOutput()
Код
C++ (Qt)
void MainWindow::setOutput(QString msg)
{
  ui->textEdit->insertPlainText(msg);
}
Но все равно что-то не то.
Кстати, еще по теме, как корректно завершить поток, чтобы не получалось:
Код:
QThread: Destroyed while thread is still running
Оно возникает, насколько я понял из-за того, что приложение завершилось, а поток нет?
Записан
Az
Гость
« Ответ #6 : Май 02, 2010, 21:23 »

Нашел один серьезный косяк, из-за которого и сыпались "QThread: Destroyed while thread is still running"
У меня создание потока висело в стеке на обработчике кнопки, по выходу из котрого он благополучно умирал. Объявил
Код
C++ (Qt)
ServerThread *th = new ServerThread;
и ошибки прекратились, в массив bytes данные заносятся, но дальше не идет, вылетает...
Записан
Az
Гость
« Ответ #7 : Май 02, 2010, 21:59 »

Проблема решена, тема закрыта.
Я, дурак, обращался к несуществующему объекту process.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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