如何在QT中安全地终止在不同线程上运行的对象

时间:2012-03-03 20:04:20

标签: c++ multithreading qt signals-slots

我正在学习如何在不同的线程上运行对象。我从这个简单的练习开始,在不同的线程上运行对象并在它们之间进行通信。现在,我无法终止程序。主要退出时如何安全地销毁在不同线程中运行的对象?如果我在main之前对线程进行等待以完成线程,程序将挂起在wait()。如果我没有等待,则永远不会执行线程,并且主要退出时会立即删除线程。

    --------testthread.h------------------
    #ifndef TESTTHREAD_H
    #define TESTTHREAD_H

   #include <QThread>
   #include <QApplication>
   #include <string>
   #include <iostream>

   using namespace std;
   class testThread : public QObject
   {
     Q_OBJECT
     public:
     testThread(const string&, QThread*);
    ~testThread();
private:
    QThread* thread;
    string _threadName;
signals:
    void requestCalculateSquare(int);
public slots:
    void calculateSquare(int);
    void start();

  };

   #endif // TESTTHREAD_H}

   -----testthread.cpp---------------------
   #include "testthread.h"
   #include <iostream>
   //#include "moc_testthread.cpp"

   testThread::~testThread()
   {}

   testThread::testThread(const string& threadName, QThread* thread):QObject()
   {
      _threadName = threadName;
       moveToThread(thread);
       connect(thread, SIGNAL(started()),this,SLOT(start()));
   }

   void testThread::calculateSquare(int i)
   {
      cout<<_threadName<<" "<<i*i;
   }

   void testThread::start()
    {
       for(int i=0;i<10;++i)
       {
         emit requestCalculateSquare(i);
       }
         emit finished();
    }

     --------main.cpp--------------------------
    #include <iostream>
    #include <QtCore/QCoreApplication>
    #include <string> 
    #include "testthread.h"

    using namespace std;

    int main(int argc, char** argv)
    {
       QApplication app(argc,argv);
       string name1("Thread1");
       string name2("Thread2");
       QThread* thread1 = new QThread;
       QThread* thread2 = new QThread;
       testThread*  test1 = new testThread(name1, thread1);
       testThread* test2 = new testThread(name2, thread2);

         QObject::connect(test1,SIGNAL(requestCalculateSquare(int)),test2,SLOT(calculateSquare(int)));
QObject::connect(test2,SIGNAL(requestCalculateSquare(int)),test1,SLOT(calculateSquare(int)));
    QObject::connect(test1,SIGNAL(finished()),test2, SLOT(deleteLater()));
    QObject::connect(test1,SIGNAL(finished()),thread2, SLOT(quit()));
    QObject::connect(test2,SIGNAL(finished()),test1, SLOT(deleteLater()));
    QObject::connect(test2,SIGNAL(finished()),thread1, SLOT(quit()));

thread1->start();
thread2->start();

thread1->wait();
thread2->wait();

cout << "Hello World!" << endl;
return 0;
//return app.exec();
}

2 个答案:

答案 0 :(得分:3)

你正在做一些时髦的事情。

1)每个QThreadstart()调用两次 - 首先在testThread构造函数中,然后再在main()中。第二个调用不会执行任何操作,因为已经在运行。

2)当您在QThread构造函数中启动testThread时,您的循环将在连接之前执行并发出信号 - 这让我觉得您实际上并不想启动该线程在构造函数中,而不是在main()中稍后将其保持为未启动。

3)QThread::quit()将导致线程的事件循环返回 - 这就是你所缺少的。 connecttestThreadquit插槽的“完成”类型信号,然后QThread::wait()将按预期运行,并且一旦完成循环,调用就会返回。 / p>

4)我知道这只是一个小测试程序,但是由于你没有在delete对象上调用new,所以你会泄漏内存。实际上你根本不需要使用new,一切都可以在堆栈上分配 - 通常是一个更好的主意。

答案 1 :(得分:0)

不要在threa \ ds上等待以防止主线程退出。可能等待STDIN或其他一些输入?

等待/加入线程只应在绝对需要时才能完成(例如,必须刷新/关闭文件,必须提交事务,必须关闭数据库连接)。如果你经常加入/等待所有线程只是因为它似乎是一个好主意,你最终会编写一大堆复杂的代码来让线程退出 - 这通常是不必要的。