LINUX.ORG.RU

Странный QProcess

 ,


0

1

Делаю я тут одну программу, все как обычно - MainWindow с GUI. По нажатию кнопки требуется запустить консольную утилиту, выход которой перехватывается и отображается в окне. Ну вот прямо в MainWindow создаю QProcess, его сигналы соединяю со слотами MainWindow, командую ему start - все работает. Так как хотелось бы все это делать в отдельном потоке - переношу код в потомка от QThread и тут всем весом попадаю на грабли. В заботливо созданные слоты потока сигнал не приходят. WTF или так и должно быть? Да, куда рыть и что искать?

★★

А зачем тебе переносить запуск QProcess в отдельный поток? Его же можно сделать неблокирующим.

grondek
()
Ответ на: комментарий от Quickern

При соединении с флагом Qt::DirectConnection, сигналы приходят после завершения работы программы.

braboar ★★
() автор топика
Последнее исправление: braboar (всего исправлений: 1)
Ответ на: комментарий от m0rph
void MainWindow::slot_start()
{
    thr = new Thread;
    thr->start();
}

void Thread::run()
{
    task = new QProcess;
    connect(task, SIGNAL(started()), this, SLOT(slot_started()), Qt::QueuedConnection);
    connect(task, SIGNAL(finished(int)), this, SLOT(slot_finished()), Qt::QueuedConnection);
    connect(task, SIGNAL(readyRead()), this, SLOT(slot_info()), Qt::QueuedConnection);
    ...
}
braboar ★★
() автор топика
Ответ на: комментарий от braboar

А зачем ты коннектишь сигналы QProcess'а к слотам Thread через Qt::QueuedConnection? Так нужно делать, если ты делаешь соединение между объектами, принадлежащими разным потокам (MainWindow и Thread в твоем случае). Более того, автоматическое подключение (Qt::AutoConnection) прекрасно справляется со своей задачей (если конечно объекты правильно раскиданы по потокам), поэтому не нужно указывать тип соединения специально.

m0rph ★★★★★
()
Последнее исправление: m0rph (всего исправлений: 2)

QProcess и так отдельный поток создаёт. Отсюда и проблемы.

anonymous
()
Ответ на: комментарий от m0rph

Там были всякие варианты, в том числе и Qt:AutoConnection, не помогло

braboar ★★
() автор топика
Ответ на: комментарий от braboar

Такое впечатление, что цикл обработки сообщений QThread чем-то заблокирован, раз сигналы приходят после завершения работы.

POLTER ★★
()
Ответ на: комментарий от braboar

А eventLoop в потоке ты звпускаешь?

void Thread::run()
{
  // process init

  exec(); // !!!!
}
grondek
()

Но вообще тебе абсолютно не нужен отдельный поток для запуска QProcess.

QProcess::start - асинхронная и совсем не блокирует поток, откуда запускается.

grondek
()
Ответ на: комментарий от braboar

Когда я не умел работать с QThread как ты сейчас, я тоже страдал... :) И зачем делать эти коннекты обязательно в run, и зачем вообще там Qt::QueuedConnection?

Смотри, я сейчас напишу как я это представляю, а другие ЛОРовцы подтвердят или опровергнут мои слова.

В основном потоке:

QThread shit_thread; // в header-е
shit_object so;
...
// далее в основном коде:
shit_thread.start();
so.moveToThread(&shit_thread);

Сам объект:

class shit_object : public QObject
{
	Q_OBJECT
...
signals:
slots:

Внутри shit_object делаешь обычные коннекты как всегда делал. Представь что shit_object это вообще обычный кусок Qt-шной программы. И всего лишь эти две строки shit_thread.start(); so.moveToThread(&shit_thread); сделают чтобы целый отдельный кусок кода, этот объект - работал в отдельном потоке. А между основными потоком и этим объектом можешь безопасно обмениваться сигналами-слотами.

Есть известная статья на эту тему, просто там гораздо сложнее описали подход, который я сейчас применяю: http://habrahabr.ru/post/150274/

т.е. фактически, объект работает в отдельном потоке с отдельным циклом обработки сообщения (который не блокирует и не мешает основному потоку) просто при помощи тупо moveToThread... И никаких там run, никаких страданий, никаких мьютексов если только сигналы-слоты, а слоты вызываются при помощи invokeMethod или просто отсылки сигналов из основного потока...

I-Love-Microsoft ★★★★★
()
Последнее исправление: I-Love-Microsoft (всего исправлений: 2)
Ответ на: комментарий от m0rph

process.start(command);

В каком потоке вызовется слот start в твоем примере? Есть мнение что при таком написании - как раз в основном потоке, что как раз не надо.

I-Love-Microsoft ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

Когда я не умел работать с QThread как ты сейчас

Вообще-то я разбирал код, доставшийся по наследству.

Есть известная статья на эту тему

You are doing it wrong? Читал...

Проблема была не в том, как запустить QThread; я его вообще убрал и оставил QProcess. Все работает.

А за советы спасибо :)

braboar ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.