Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: yegoriy от Июнь 27, 2012, 18:30



Название: GUI-поток + (поток + msleep) - засыпает всё
Отправлено: yegoriy от Июнь 27, 2012, 18:30
   Работаю с потоками недавно и столкнулся с интересным поведением.
Есть класс основного потока:

Код:
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

signals:
    void StartSomthingDo();

private slots:
    void on_pbStartThread_clicked();

private:
    Ui::MainWindow *ui;
    MyThread *TestThread;
};

и класс второстепенного потока:
Код:
class MyThread : public QThread
{
    Q_OBJECT

public:
    MyThread();

public slots:
    void StartDo();
};

Реализация выглядит примерно так:
Код:
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

MyThread::MyThread()
{

}

void MainWindow::on_pbStartThread_clicked()
{
    TestThread = new MyThread();
    connect(this,SIGNAL(StartSomthingDo()),TestThread,SLOT(StartDo()));
    TestThread->start();
    emit StartSomthingDo();
}

void MyThread::StartDo()
{
    msleep(5000);
}

Проблема заключается в следующем: метод msleep в второстепенном потоке вешает основной GUI-поток.
Собственно не могу понять из-за чего? Есть мысли по этому поводу?


Название: Re: GUI-поток + (поток + msleep) - засыпает всё
Отправлено: alexis031182 от Июнь 27, 2012, 18:35
Странная реализация. QObject::moveToThread() забыли


Название: Re: GUI-поток + (поток + msleep) - засыпает всё
Отправлено: Bepec от Июнь 27, 2012, 18:53
Алексис, вы безусловно правы, но внимательнее всмотритесь :D

Класс унаследован от потока, НО метод run не переопределён.

Интересно, поток сразу умрёт, или нет? Счас попробую аж :D



Название: Re: GUI-поток + (поток + msleep) - засыпает всё
Отправлено: alexis031182 от Июнь 27, 2012, 18:57
Алексис, вы безусловно правы, но внимательнее всмотритесь :D
Класс унаследован от потока, НО метод run не переопределён.
Интересно, поток сразу умрёт, или нет? Счас попробую аж :D
Да я понял, потому и написал, что странная реализация :)


Название: Re: GUI-поток + (поток + msleep) - засыпает всё
Отправлено: yegoriy от Июнь 27, 2012, 19:06
Метод run ,по докам, можно и не переопределять, он по-умолчанию содержит exec() - запускается цикл обработки событий. Сигнал пришёл - функция работает. В этом же вся прелесть модели сигнал-слот. Выход из потока quit() или exit(). Пример накидывал на коленках по-минимальному содержанию, посему выход и завершение потока не реализованы...


Название: Re: GUI-поток + (поток + msleep) - засыпает всё
Отправлено: alexis031182 от Июнь 27, 2012, 19:19
Если Вы наследуете QThread, то логично использовать переопределение run(). Если не наследуете, то логично использовать отдельный класс, функционал которого требуется выполнять в отдельном потоке.


Название: Re: GUI-поток + (поток + msleep) - засыпает всё
Отправлено: Bepec от Июнь 27, 2012, 19:22
Да кстати, вы правы, он по умолчанию запускает цикл :) Это я знал, но не воспринимал :D Благодаря вам знаю.

У вас одна проблема - Ваш слот является лишь обычным методом класса. Чтобы он был в другом потоке, можно сделать 2 вещи:

1) сделать moveToThread(this) в конструкторе вашего класса-потока. (мой выбор.) Тогда нет нужды в 2 классах, но теряется гибкость переноса вашего класса в другой поток (а оно вам надо? :P)

2) создать отдельный класс с этим слотом, далее создать QThreadName и сделать moveToThread(QThreadName). Выбор других людей на этом форуме, например alexis031182. :)

Оба способа имеют свои преимущества и недостатки. Но они равноправны :D


Название: Re: GUI-поток + (поток + msleep) - засыпает всё
Отправлено: Igors от Июнь 27, 2012, 19:24
В очередной раз moveToThread. Слот вызывается в главной нитке, ну ее и вешает. Попечатайте currentThreadID в слоте чтобы убедиться