多线程中的信号与槽(上)
值得思考的问题:
线程类的信号与槽
实验一:
TestThread.h
#ifndef TESTTHREAD_H #define TESTTHREAD_H #include <QThread> class TestThread : public QThread { Q_OBJECT protected: void run(); public: TestThread(); signals: void testSignal(); protected slots: void testSlot(); }; #endif // TESTTHREAD_H
TestThread.cpp
#include "TestThread.h" #include <QDebug> TestThread::TestThread() { connect(this,SIGNAL(testSignal()),this,SLOT(testSlot())); } void TestThread::run() { qDebug() << "void TestThread::run() begin..."; for(int i=0; i<10; i++) { qDebug() << "void TestThread::run() i = " << i; sleep(1); } emit testSignal(); //发射的信号谁来接收呢,可以在构造函数中将信号和槽函数进行关联。 qDebug() << "void TestThread::run() end..."; } void TestThread::testSlot() { qDebug() << "void TestThread::testSlot()"; }
main.cpp
#include <QCoreApplication> #include "TestThread.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); TestThread t; t.start(); return a.exec(); }
实验二:在上面实验的基础上增加类MyObject.h
MyObject.h
#ifndef MYOBJECT_H #define MYOBJECT_H #include <QObject> class MyObject : public QObject { Q_OBJECT public: MyObject(); protected slots: void getStarted(); void getFinished(); void getTeminated(); }; #endif // MYOBJECT_H
MyObject.cpp
#include "MyObject.h" #include <QObject> #include <QDebug> MyObject::MyObject() { } void MyObject::getStarted() { qDebug() <<"void MyObject::getStarted()" ; } void MyObject::getFinished() { qDebug() << "void MyObject::getFinished()"; } void MyObject::getTeminated() { qDebug() << "void MyObject::getTeminated()"; }
main.cpp
#include <QCoreApplication> #include "TestThread.h" #include "MyObject.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); TestThread t; MyObject m; QObject::connect(&t,SIGNAL(started()),&m,SLOT(getStarted())); QObject::connect(&t,SIGNAL(finished()),&m,SLOT(getFinished())); // QObject::connect(&t,SIGNAL(terminated()),&m,SLOT(getTeminated())); t.start(); return a.exec(); }
让人逃避的问题:
问题:如果程序中有多个线程,槽函数是在哪个线程中执行?
概念小科普
进程中存在栈空间的概念
栈空间专用于函数调用(保存函数参数,局部变量,等)
线程拥有独立的栈空间(可调用其他函数)
小结论:
只要函数体中没有访问临界资源的代码,同一个函数可以被多个线程同时调用,且不会产生任何副作用。
实验前的准备:
操作系统通过整型标识管理进程和线程
进程拥有全局唯一的ID值(PID)
线程有进程内唯一的ID值(TID)
QThread中的关键静态成员函数
QThread* currentThread()
Qt::HANDLE currentThreadId()
槽函数的运行上下文
main.cpp
#include <QCoreApplication> #include <QThread> #include <QDebug> #include "TestThread.h" #include "MyObject.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); qDebug() << "main tid() " << QThread::currentThreadId(); TestThread t; MyObject m; QObject::connect(&t,SIGNAL(started()),&m,SLOT(getStarted())); QObject::connect(&t,SIGNAL(finished()),&m,SLOT(getFinished())); // QObject::connect(&t,SIGNAL(terminated()),&m,SLOT(getTeminated())); t.start(); return a.exec(); }
MyObject.cpp
#include "MyObject.h" #include <QObject> #include <QThread> #include <QDebug> MyObject::MyObject() { } void MyObject::getStarted() { qDebug() <<"void MyObject::getStarted()tid = " << QThread::currentThreadId() ; } void MyObject::getFinished() { qDebug() << "void MyObject::getFinished()tid = " << QThread::currentThreadId() ; } void MyObject::getTeminated() { qDebug() << "void MyObject::getTeminated()tid = " << QThread::currentThreadId() ; }
TestThread.cpp
#include "TestThread.h" #include <QDebug> TestThread::TestThread() { connect(this,SIGNAL(testSignal()),this,SLOT(testSlot())); } void TestThread::run() { qDebug() << "void TestThread::run() begin...tid = " << currentThreadId(); for(int i=0; i<10; i++) { qDebug() << "void TestThread::run() i = " << i; sleep(1); } emit testSignal(); //发射的信号谁来接收呢,可以在构造函数中将信号和槽函数进行关联。 qDebug() << "void TestThread::run() end..."; } void TestThread::testSlot() { qDebug() << "void TestThread::testSlot() tid = " << currentThreadId(); }
从上面的打印结果看,槽函数的执行都是在主线程中执行的,但事实真的如此吗?后续将会继续讨论。