Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我可以将QObject的两个子类移动到同一个QThread吗?_C++_Multithreading_Qt_Qthread - Fatal编程技术网

C++ 我可以将QObject的两个子类移动到同一个QThread吗?

C++ 我可以将QObject的两个子类移动到同一个QThread吗?,c++,multithreading,qt,qthread,C++,Multithreading,Qt,Qthread,我有两个子类QObject: class Worker : public QObject { Q_OBJECT public: explicit Worker(QObject *parent = 0); signals: public slots: void process(); }; 及 我将工作线程和控制器移动到相同的QThread。我想通过ThreadController和正在工作的工作人员来控制线程(进入睡眠或醒来),现在这个想法不起作用了,工作人员可以完

我有两个子类
QObject

class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(QObject *parent = 0);

signals:

public slots:
    void process();
};


我将工作线程和控制器移动到相同的
QThread
。我想通过
ThreadController
和正在工作的工作人员来控制线程(进入睡眠或醒来),现在这个想法不起作用了,工作人员可以完成进程,但控制器不能工作,我不知道我的代码出了什么问题。

谢谢@thuga是的,正如你所说的。Worker::process是一个无限循环,如下所示:

void Worker::process(){

    int a=(int)QThread::currentThreadId();
    emit sendThreadId(a);
    int b=0;
    while (b<1000000) {
       b++;
       emit processResult(b);
       QThread::msleep(1);// signal emit too quickly will block the main thread,                 
                          //so i just let the loop slow down 
   }
}
是的,直接连接让它工作。谢谢!我还有一些问题:当QThread使用QWaitCondition::wait()时,它会停止其中的事件循环吗?那么发送到线程的任何信号都将不再被处理


我想在我的程序中重用QThread。当工作线程完成其工作时,将向控制器发送一个信号,控制器将执行sleep()函数。下次数据到来时,控制器将唤醒()线程,工作线程将再次工作。有其他解决方案适合这种情况吗?重用QThread或删除它并重新创建它(哪种性能损失更大)?

@thuga我需要workerthread中的信号和插槽。但是QtConcurrent::run无法提供这样的机制。您应该知道,我们不必在无事可做的情况下让线程休眠。在你的帮助下,我刚刚完成了这项工作。虽然我的解决方案不好,但我发布了所有代码,如下所示:

从事繁重工作的工人阶级

class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(QObject *parent = 0);

signals:
    void processResult(int);
    void sendThreadId(int);

public slots:
    void process();
};

void Worker::process(){
  QEventLoop eventloop;
  int a=(int)QThread::currentThreadId();
  emit sendThreadId(a);
  int b=0;
   while (b<1000000) {
      b++;
      emit processResult(b);
      QThread::msleep(1);
      eventloop.processEvents();
  }
    qDebug()<<"Worker::process() called";
    qDebug()<<QThread::currentThreadId();
    eventloop.exec();
}


该方案:
ThreadController::ThreadController(QObject*parent):QObject(parent){mutex=new QMutex();wc=new QWaitCondition();}Worker::process看起来像什么?那里有无限循环吗?如果是这样,则永远不会执行
ThreadController::sleep
。此外,您必须从其他线程唤醒该线程,因此
ThreadController::wakeUp
将无法使用您的信号/插槽方法(除非您将其设置为直接连接)。@thuga您是否介意就QWaitCondition无法停止无限循环的原因向我提供更多建议。我在网上搜索了很长时间。但是没有用。请提供帮助或尝试给出一些实现方法。由于
ThreadController::sleep()
方法是一个槽(应该是这样),并且无限循环会阻止事件循环,因此
sleep
槽永远不会执行。如果在线程中使用插槽,则不应使用无限循环。如果要模拟无限循环,请使用
QTimer
。现在我知道了。当工作线程执行无限循环时,它会阻塞线程的事件循环。因此,执行sleep()的信号将不会被处理,但wakeup()函数将被执行,因为我只在唤醒插槽的连接中使用了Qt::DirectConnection。DirectConnection只允许wakeup()在主线程中运行,因为唤醒信号是从主线程发出的。正确。您只需再次使用
QTimer
@thuga thx替换无限循环即可。我还有另一个问题:使用QWaitCondition重用QThread是否值得?或者只是在需要时新建一个QThread。创建一个线程将消耗大量资源?你是什么意思?以何种方式重用?@thuga重用方式:当工作线程完成其工作时,它将向控制器发送一个睡眠信号,控制器将让workerthread进入睡眠状态。当新数据出现时,控制器将唤醒workerthread,工作线程将重新开始工作。这样做值得吗?或者在需要时创建一个新的QThread。
QObject::connect(&w,&MainWindow::wakeClicked,controller,&ThreadController::wakeUp,Qt::DirectConnection);
class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(QObject *parent = 0);

signals:
    void processResult(int);
    void sendThreadId(int);

public slots:
    void process();
};

void Worker::process(){
  QEventLoop eventloop;
  int a=(int)QThread::currentThreadId();
  emit sendThreadId(a);
  int b=0;
   while (b<1000000) {
      b++;
      emit processResult(b);
      QThread::msleep(1);
      eventloop.processEvents();
  }
    qDebug()<<"Worker::process() called";
    qDebug()<<QThread::currentThreadId();
    eventloop.exec();
}
class ThreadController : public QObject
{
    Q_OBJECT
public:
    explicit ThreadController(QObject *parent = 0);
    ~ThreadController();
signals:
      void statusChanged(QString);
public slots:
    void sleep();
    void wakeUp();
private:
    QMutex *mutex;
    QWaitCondition *wc;
};

ThreadController::ThreadController(QObject *parent) : QObject(parent)
{
    mutex=new QMutex();
    wc=new QWaitCondition();
}

ThreadController::~ThreadController(){
   delete mutex;
   delete wc;
}

void ThreadController::sleep(){
    qDebug()<<"ThreadController::sleep() called";
    qDebug()<<QThread::currentThreadId();
    emit statusChanged("WorkerThread sleeping");
    mutex->lock();
    wc->wait(mutex);
    mutex->unlock();
}

void ThreadController::wakeUp(){
    qDebug()<<"ThreadController::wakeUp() called";
    qDebug()<<QThread::currentThreadId();
    emit statusChanged("WorkerThread wakening");
    mutex->lock();
    wc->wakeAll();
    mutex->unlock();
}
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();
signals:
    void wakeClicked();
    void sleepClicked();
public slots:
    void setMainId(int);
    void setThreadId(int);
    void setThreadStatus(QString);
    void setThreadCount(int);
private:
     QLabel*l_mainThreadId;
     QLabel*l_workerThreadId;
     QLabel*l_workerThreadStatus;
     QLabel*l_workerThreadCount;
     QString count;
};

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{

    setWindowTitle("Threading Test");
    QWidget *window=new QWidget;

    QVBoxLayout *mainLayout=new QVBoxLayout;
    QHBoxLayout *mainLayout1=new QHBoxLayout;
    QHBoxLayout *mainLayout2=new QHBoxLayout;

    QLabel*label1=new QLabel("Main Thread ID:");
    l_mainThreadId=new QLabel;

    int a=(int)QThread::currentThreadId();
    QString idlabel=QString::number(a);
    l_mainThreadId->setText(idlabel);

    mainLayout1->addWidget(label1);
    mainLayout1->addWidget(l_mainThreadId);

    QPushButton* wakeButton=new QPushButton("WakeUp");
    QPushButton*sleepButton=new QPushButton("Sleep");

    mainLayout2->addWidget(wakeButton);
    mainLayout2->addWidget(sleepButton);

    mainLayout->addLayout(mainLayout1);
    mainLayout->addLayout(mainLayout2);


    QVBoxLayout *threadLayout=new QVBoxLayout;
    QHBoxLayout *threadLayout1=new QHBoxLayout;
    QHBoxLayout *threadLayout2=new QHBoxLayout;
    QHBoxLayout *threadLayout3=new QHBoxLayout;

    QLabel *label2=new QLabel("Worker Thread ID:");
    l_workerThreadId=new QLabel;

    threadLayout1->addWidget(label2);
    threadLayout1->addWidget(l_workerThreadId);

    QLabel *label3=new QLabel("Worker Thread Status:");
    l_workerThreadStatus=new QLabel;

    threadLayout2->addWidget(label3);
    threadLayout2->addWidget(l_workerThreadStatus);

    QLabel *label4=new QLabel("Counting Result:");
    l_workerThreadCount=new QLabel;

    threadLayout3->addWidget(label4);
    threadLayout3->addWidget(l_workerThreadCount);

    threadLayout->addLayout(threadLayout1);
    threadLayout->addLayout(threadLayout2);
    threadLayout->addLayout(threadLayout3);

    QHBoxLayout *layout=new QHBoxLayout;
    layout->addLayout(mainLayout);
    layout->addLayout(threadLayout);

    window->setLayout(layout);

    setCentralWidget(window);
    setThreadStatus("WorkerThread wakening");

    QObject::connect(wakeButton,&QPushButton::clicked,this,&MainWindow::wakeClicked);
    QObject::connect(sleepButton,&QPushButton::clicked,this,&MainWindow::sleepClicked);

}

MainWindow::~MainWindow()
{

}

void MainWindow::setMainId(int id){

   QString idlabel=QString::number(id);
   l_mainThreadId->setText(idlabel);

}

void MainWindow::setThreadId(int id){

     QString idlabel=QString::number(id);
     l_workerThreadId->setText(idlabel);
}

void MainWindow::setThreadStatus(QString s){

    l_workerThreadStatus->setText(s);
}

void MainWindow::setThreadCount(int i){
    count = QString::number (i) ;
    l_workerThreadCount->setText(count);
}
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    QThread* thread = new QThread;
    Worker* worker = new Worker;
    ThreadController*controller=new ThreadController();
    controller->moveToThread(thread);
    worker->moveToThread(thread);

    QObject::connect(thread,&QThread::started,worker,&Worker::process);    QObject::connect(worker,&Worker::processResult,&w,&MainWindow::setThreadCount);
    QObject::connect(worker,&Worker::sendThreadId,&w,&MainWindow::setThreadId);
    QObject::connect(&w,&MainWindow::wakeClicked,controller,&ThreadController::wakeUp,Qt::DirectConnection);
    QObject::connect(&w,&MainWindow::sleepClicked,controller,&ThreadController::sleep);
    QObject::connect(controller,&ThreadController::statusChanged,&w,&MainWindow::setThreadStatus);

    thread->start();
    return a.exec();
}