QThread使用

6 篇文章 0 订阅

QT assistant 中通过QThread创建子线程有两种方法。

方法1:

class Worker : public QObject
 {
     Q_OBJECT
     QThread workerThread;

 public slots:
     void doWork(const QString &parameter) {
         // ...
         emit resultReady(result);
     }

 signals:
     void resultReady(const QString &result);
 };

 class Controller : public QObject
 {
     Q_OBJECT
     QThread workerThread;
 public:
     Controller() {
         Worker *worker = new Worker;
         worker->moveToThread(&workerThread);
         connect(workerThread, SIGNAL(finished()), worker, SLOT(deleteLater()));
         connect(this, SIGNAL(operate(QString)), worker, SLOT(doWork(QString)));
         connect(worker, SIGNAL(resultReady(QString)), this, SLOT(handleResults(QString)));
         workerThread.start();
     }
     ~Controller() {
         workerThread.quit();
         workerThread.wait();
     }
 public slots:
     void handleResults(const QString &);
 signals:
     void operate(const QString &);
 };


方法2:

class WorkerThread : public QThread
 {
     Q_OBJECT
     void run() {
         QString result;
         /* expensive or blocking operation  */
         emit resultReady(result);
     }
 signals:
     void resultReady(const QString &s);
 };

 void MyObject::startWorkInAThread()
 {
     WorkerThread *workerThread = new WorkerThread(this);
     connect(workerThread, SIGNAL(resultReady(QString)), this, SLOT(handleResults(QString)));
     connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
     workerThread->start();
 }

void QObject::deleteLater () [slot]

Schedules this object for deletion.

The object will be deleted when control returns to the event loop. If the event loop is not running when this function is called (e.g. deleteLater() is called on an object beforeQCoreApplication::exec()), the object will be deleted once the event loop is started. If deleteLater() is called after the main event loop has stopped, the object will not be deleted. Since Qt 4.8, if deleteLater() is called on an object that lives in a thread with no running event loop, the object will be destroyed when the thread finishes.

Note that entering and leaving a new event loop (e.g., by opening a modal dialog) will not perform the deferred deletion; for the object to be deleted, the control must return to the event loop from which deleteLater() was called.

Note: It is safe to call this function more than once; when the first deferred deletion event is delivered, any pending events for the object are removed from the event queue.


我的工程中用了第二种方法

WorkThread.hpp:

class WorkerThread : public QThread
{
	Q_OBJECT

public:
	typedef enum
	{
		Thread_Invalid,
		Create_Thread_Failed,
		Thread_Finished
	} Thread_Result_EN;

	WorkerThread(const QString &strCmd, const QString &strLog) : \
		 m_enState(Thread_Invalid),m_strCMD(strCmd),m_strLogFile(strLog){}
	
	Thread_Result_EN currentState(void){return m_enState;}

protected:
	virtual void run();

private:
	Thread_Result_EN m_enState;
	QString m_strCMD, m_strLogFile;

Q_SIGNALS:
	void resultReady(Thread_Result_EN enResult);
};

WorkThread.cpp:

void WorkerThread::run()
{
	std::string strCmd = std::string((const char*)(m_strCMD.toLocal8Bit()));
	std::string strLog = std::string((const char*)(m_strLogFile.toLocal8Bit()));

#ifdef WIN32
	STARTUPINFO sInfo;
	PROCESS_INFORMATION pInfo;

	ZeroMemory(&sInfo, sizeof(STARTUPINFO));
	ZeroMemory(&pInfo, sizeof(PROCESS_INFORMATION));
	sInfo.cb = sizeof(STARTUPINFO);

	sInfo.dwFlags = STARTF_USESTDHANDLES;
	sInfo.wShowWindow = SW_HIDE;

	SECURITY_ATTRIBUTES saAttr; 
	saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
	saAttr.bInheritHandle = TRUE; 
	saAttr.lpSecurityDescriptor = NULL; 

	HANDLE hrFile, hwFile;
	if(!CreatePipe(&hrFile, &hwFile,         
		&saAttr, NULL))
	{
		m_enState = Create_Thread_Failed;
		emit resultReady(Create_Thread_Failed);
		return;
	}

	HANDLE hStdO = CreateFileA(strLog.c_str(),
		FILE_APPEND_DATA,             
		FILE_SHARE_WRITE | FILE_SHARE_READ,
		&saAttr,                     
		CREATE_ALWAYS,           
		FILE_ATTRIBUTE_NORMAL,   
		NULL);                   

	if (INVALID_HANDLE_VALUE == hStdO)
	{
		m_enState = Create_Thread_Failed;
		emit resultReady(Create_Thread_Failed);
		return;
	}

	sInfo.hStdOutput = hStdO;
	sInfo.hStdError = hStdO;

	BOOL bRetVal = CreateProcessA(NULL,
		(LPSTR)strCmd.c_str(),
		NULL,
		NULL,
		TRUE,
		CREATE_NO_WINDOW,
		NULL,
		NULL,
		(LPSTARTUPINFOA)&sInfo,
		&pInfo
		);

	if(!bRetVal)
	{
		m_enState = Create_Thread_Failed;
		emit resultReady(Create_Thread_Failed);
		return;
	}

	WaitForSingleObject(pInfo.hProcess, INFINITE);
	CloseHandle(pInfo.hProcess);
	CloseHandle(pInfo.hThread);

#else
	string strrun = strCmd + " > " + strLog + " 2>&1";
	system(strrun.c_str());
#endif

	m_enState = Thread_Finished;
	emit resultReady(Thread_Finished);
}

main.cpp:

    WorkerThread wthEvtSetup("perl \"./event_setup_generator.pl\"", "./perl.log");
    //connect(&wthEvtSetup, SIGNAL(finished()), this, SLOT(deleteLater()));
#if 0
    connect(&wthEvtSetup, SIGNAL(resultReady(WorkerThread::Thread_Result_EN)), this, SLOT(_EventSetupFinished(WorkerThread::Thread_Result_EN)));
    wthEvtSetup.start();
    wthEvtSetup.wait();
#else
    wthEvtSetup.start();
    wthEvtSetup.wait();

    QMessageBox::warning(this, QString("run DebugModule"), QString("process create failed!"));
    _EventSetupFinished(wthEvtSetup.currentState());
#endif
 加上被注释的那一句,QMessageBox就会coredump,具体原因应该是deleteLater()导致的。 

但这里wthEvtSetup的run()中发出的信号resultReady()却没能触发_EventSetupFinished(),不明白为什么?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
QThreadQt框架用于多线程编程的类。通过继承QThread类,可以创建自定义的线程类,并在其实现自己的线程逻辑。下面是一个使用QThread的示例代码: 在ThreadController.hppThreadController类继承自QObject,并包含一个QThread对象workerThread。在构造函数,创建了一个ThreadWorker对象threadWork,并将其移交给workerThread线程。通过QObject::connect函数连接了一个信号和槽函数,当发出touchWork信号时,会触发threadWork的work槽函数。然后启动workerThread线程,并发出touchWork信号,从而触发线程执行工作。 在main.cpp,创建了一个QCoreApplication对象a,并打印了主线程的ID。然后创建了一个CustomThread对象customThread,并通过QObject::connect函数连接了一个信号和槽函数。最后调用customThread的start函数启动线程。 在CustomThread.hpp,CustomThread类继承自QThread。在run函数,打印了当前线程的ID,并通过QThread::sleep函数模拟了线程的工作。然后发出customThreadSignal信号,从而触发customThreadSlot槽函数。 综上所述,QThread使用方法是通过继承QThread类,重写run函数,在其实现线程的逻辑。可以通过信号和槽函数来与其他线程进行通信。 #### 引用[.reference_title] - *1* *2* *3* [QT 线程QThread使用方式](https://blog.csdn.net/weixin_41111116/article/details/126372972)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值