QT信號槽連接之不同線程之間的信號槽連接方式

QT中信號槽的連接方式有五種:
Qt::AutoConnection
信號槽默認的連接方式,如果信號與槽在同一線程,就自動採用Qt::DirectConnection,
如果信號與槽不在同一線程,將自動採用Qt::QueuedConnection的連接方式。

Qt::DirectConnection
Qt::DirectConnection表示一旦信號產生,立即執行槽函數。 (如果主線程發送信號給子線程,則這個參數要使用 Qt::DirectConnection ,槽函數在子線程中立即執行)

Qt::QueuedConnection
在不同的線程中處理, Qt::QueuedConnection表示將發送信號給接受線程,並且進入接收線程的隊列,等候處理,像是Win32中PostMessage

Qt::BlockingQueuedConnection
在不同的線程中處理,當前線程信號發送後,會阻塞等待,接收線程處理完成後纔會返回,發送線程會進行下一步的處理 。
但是如果在一個線程中使用這種信號槽的連接方式,會是怎麼樣的呢?
在運行的時候,程序會一直卡在發送信號的地方,並不會報錯但是,會輸出一下信息:

Qt: Dead lock detected while activating a BlockingQueuedConnection: Sender is QtManager(0xfc3f8c3a40), receiver is QtManager(0xfc3f8c3a40)

出現了死鎖現象。
信號槽的連接可以在在一個地方,但是發送信號的地方和槽函數的地方必須在兩個線程中才可以

Qt::UniqueConnection
Qt::UniqueConnection表示只有它不是一個重複連接,連接纔會成功。如果之前已經有了一個鏈接(相同的信號連接到同一對象的同一個槽上),那麼連接將會失敗並將返回false。

例如:

#pragma once

#include <QThread>

class MyThread : public QThread {
	Q_OBJECT

public:
	MyThread(QObject *parent);
	~MyThread();

	void run()override;

private:
	int _count = 0;
};

#include "MyThread.h"
#include "QtManager.h"
#include <QDebug>
MyThread::MyThread(QObject *parent)
	: QThread(parent) {
}

MyThread::~MyThread() {
}

void MyThread::run() {
	while (true) {
		msleep(800);
		_count++;
		Mgr()->setTextInThread(QString::number(_count));
		qDebug() << QString("MyThread:%1").arg(_count);
	}
}

#pragma once
#include <QString>
class IText {
public:
	IText();
	~IText();

	virtual void setText(QString t);
};


#include "IText.h"

IText::IText() {
}

IText::~IText() {
}

void IText::setText(QString t) {

}

#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_QtGuiThread.h"
#include "IText.h"

class MyThread;

class QtGuiThread : public QMainWindow ,public IText {
	Q_OBJECT

public:
	QtGuiThread(QWidget *parent = Q_NULLPTR);

	virtual void setText(QString t)override;
private:
	void init();

private slots:
	void slotStart();
private:
	Ui::QtGuiThreadClass ui;
	MyThread* _myThread = nullptr;
};

#include "QtGuiThread.h"
#include "MyThread.h"
#include "QtManager.h"

QtGuiThread::QtGuiThread(QWidget *parent)
	: QMainWindow(parent) {
	ui.setupUi(this);
	init();
}

void QtGuiThread::setText(QString t) {
	ui.lineEdit->setText(t);
}

void QtGuiThread::init() {
	Mgr()->setIText(this);
	connect(ui.pushButton, SIGNAL(clicked()), this, SLOT(slotStart()));
	_myThread = new MyThread(nullptr);
}

void QtGuiThread::slotStart() {
	_myThread->start();
}

aaa

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章