一、目錄
轉載1: http://my.oschina.NET/fanhuazi/blog/737224?ref=myread 點擊打開鏈接
轉載2: http://www.qtcn.org/bbs/read-htm-tid-60505-ds-1-page-1.html#172183 點擊打開鏈接
二、內容
由於以下兩篇轉載文章都使用了C++11 新特性“lamda表達式”,為了方便同仁閱讀以下內容,在此引用一片文章對“C++11 lamda表達式”做一個簡要介紹:
“C++11 lamda表達式” ,點擊此鏈接先了解C++11新增語法,對后面內容的閱讀會有幫助。
轉載1: http://my.oschina.Net/fanhuazi/blog/737224?ref=myread 點擊打開鏈接
在Qt中將函數發送到主線程執行
……(省略部分內容,完成內容請參看上面的原文鏈接)數據共享的問題,試想“后台線程(非UI線程)中的數據如何能夠被前台(UI線程)所使用,而且前台后台不一定在一個類里面?把數據打包通過信號傳給前台?”想想就是很麻煩的事情,難道每個這樣的需求場合都要做一遍這樣的事情嗎?感謝時間,因為時間穿過2011年,C++的新標准已經完美的解決了這個問題,那就是函數對象。
Qt的4.8.6版本所使用的mingw4.9.2版本是支持C++11的,如果你用的是老掉牙的rhel5系統,則需要升級編譯器了,因為C++11要在GCC 4.5以上的版本中才會支持。
首先我們定義一個類:FunctionTransfer(函數大挪移),這個類繼承自QObject,並使用Q_OBJECT標簽來使用信號槽機制。代碼中的“std::tr1::function<void()>”就是C++標准庫中大名鼎鼎的函數對象。
- class FunctionTransfer : public QObject
- {
- Q_OBJECT
- public:
- ///@brief 構造函數
- explicit FunctionTransfer(QObject *parent = 0);
- public:
- ///@brief 制定函數f在main中執行
- static void execinmain(std::tr1::function<void()> f);
- signals:
- ///@brief 在別的線程有函數對象傳來
- void comming(std::tr1::function<void()> f);
- public slots:
- ///@brief 執行函數對象
- void exec(std::tr1::function<void()> f);
- };
然后是源文件:
- //在全局數據區實例化一個FunctionTransfer的實例,該實例所在的縣城就是主線程。
- FunctionTransfer main_thread_forward;
- void FunctionTransfer::execinmain(std::tr1::function<void()> f)
- {
- main_thread_forward.exec(f);
- }
- FunctionTransfer::FunctionTransfer(QObject *parent) :
- QObject(parent)
- {
- connect(this,SIGNAL(comming(std::tr1::function<void()>)),this,SLOT(exec(std::tr1::function<void()>)),Qt::BlockingQueuedConnection);
- }
- void FunctionTransfer::exec(std::tr1::function<void()> f)
- {
- if(Gt::isMainThread())
- {
- f();
- }
- else
- {
- emit this->comming(f);
- }
- }
非常簡單的邏輯,如果在主線程就執行,如果不是在主線程就發給主線程,主線程接到之后就執行。
類有了,接下來考慮實用的場合,比如有一個類 A,A有個方法f不能再后台執行,需要跑到前台,怎么辦呢,上代碼:
- FunctionTransfer::execinmain([this](){this->f();});
作為參數的lamda表達式捕獲了類A的this指針,然后轉換為C++的函數對象,然后跑到前台去執行了,執行完成后才會返回,是不是灰常簡潔。
轉載2:http://www.qtcn.org/bbs/read-htm-tid-60505-ds-1-page-1.html#172183 點擊打開鏈接
- #pragma once
- #include <qthread.h>
- #include <functional>
- class QIoService : QObject
- {
- public:
- QIoService(bool startinthread)
- {
- if(startinthread)
- {
- worker=new QThread(NULL);
- worker->start();
- this->moveToThread(worker);
- }
- else
- {
- //this object is created in create thread!!!
- }
- }
- void post(std::function<void()> func);
- void send(std::function<void()> func);
- void post(std::function<void()> func,int ms);
- void send(std::function<void()> func,int ms);
- virtual bool event ( QEvent * e);
- protected:
- QThread *worker;
- };
- //this should run in mainthread
- extern QIoService *main_ioservice;
- #include "stdafx.h"
- #include "qioservice.h"
- #include <qapplication.h>
- #include <qtconcurrentrun.h>
- QIoService *main_ioservice=NULL;
- class FunctionEvent : public QEvent
- {
- public:
- static const QEvent::Type myType = static_cast<QEvent::Type>(2000);
- FunctionEvent(std::function<void()> f)
- :QEvent(myType)
- {
- func=f;
- }
- ~FunctionEvent()
- {
- //這個他會自動刪除
- }
- std::function<void()> func;
- };
- void QIoService::post(std::function<void()> func)
- {
- QApplication::instance()->postEvent(this,new FunctionEvent(func));
- }
- void QIoService::send(std::function<void()> func)
- {
- QApplication::instance()->sendEvent(this,new FunctionEvent(func));
- }
- void QIoService::post(std::function<void()> func,int ms)
- {
- auto lam = [&]()
- {
- QThread::currentThread()->wait(ms);
- post(func);
- };
- QtConcurrent::run(lam);
- }
- void QIoService::send(std::function<void()> func,int ms)
- {
- auto lam = [&]()
- {
- QThread::currentThread()->wait(ms);
- send(func);
- };
- QtConcurrent::run(lam);
- }
- bool QIoService::event ( QEvent * e)
- {
- if(e->type()==FunctionEvent::myType)
- {
- FunctionEvent *fe=(FunctionEvent *)e;
- fe->func();
- return true;
- //這個他會自動刪除,不用我們自己手工delete
- }
- return false;
- }
注解:
- //比如你在另外一個線程,你收到數據,想修改界面。就弄個全局變量
- QIoService g_ui_ios(false);
- //你要把某段事情丟到其他線程執行,就
- g_worker_ios.send([]
- {
- //這段會在其他線程執行。
- 如果執行完了,又想在主線程執行某段,這里可以繼續
- //g_ui_ios.send([]
- {
- //這段會在主線程執行
- });
- });
三、更新
2016年8月27日 第一次更新
http://blog.csdn.net/qq2399431200/article/details/52335517

