Qt:让任意线程执行一个匿名函数
来源:互联网 发布:淘宝买家秀 珍珠内裤 编辑:程序博客网 时间:2024/06/14 10:38
本类主要功能是在当前线程(比如说主线程),指派任意一个线程(比如说某个工作线程)去执行一个匿名函数。
注意,这个和QtConcurrent配合QThreadPool不一样,QtConcurrent配合QThreadPool只能指派回调到QThreadPool中的线程。
而这个类可以指派一个回调到任意线程。
两个主要接口
JasonQt_InvokeFromThread::invoke:非阻塞,只是将回调放到队列中,等待执行
JasonQt_InvokeFromThread::waitForInvoke:阻塞,函数执行完成后才回返回
代码部分:
.h文件内容:
#include <QThread>#include <QMap>#include <QDebug>class JasonQt_InvokeFromThreadHelper: public QObject{ Q_OBJECTprivate: QMutex m_mutex; QList< std::function<void()> > m_waitCallbacks;public: void addCallback(const std::function<void()> &callback);public slots: void onRun();};class JasonQt_InvokeFromThread{private: static QMutex g_mutex; static QMap< QThread *, JasonQt_InvokeFromThreadHelper * > g_helpers;public: static void invoke(QThread *thread, const std::function<void()> &callback); static void waitForInvoke(QThread *thread, const std::function<void()> &callback);};
.cpp文件内容
// JasonQt_InvokeFromThreadHelpervoid JasonQt_InvokeFromThreadHelper::addCallback(const std::function<void ()> &callback){ m_mutex.lock(); m_waitCallbacks.push_back(callback); m_mutex.unlock();}void JasonQt_InvokeFromThreadHelper::onRun(){ if(!m_waitCallbacks.isEmpty()) { m_mutex.lock(); auto callback = m_waitCallbacks.first(); m_waitCallbacks.pop_front(); m_mutex.unlock(); callback(); }}// JasonQt_InvokeFromThreadQMutex JasonQt_InvokeFromThread::g_mutex;QMap< QThread *, JasonQt_InvokeFromThreadHelper * > JasonQt_InvokeFromThread::g_helpers;void JasonQt_InvokeFromThread::invoke(QThread *thread, const std::function<void ()> &callback){ if(!(thread->isRunning())) { qDebug() << "JasonQt_InvokeFromThread::invoke: Target thread" << thread << "is not running!"; return; } g_mutex.lock(); auto it = g_helpers.find(thread); if(it == g_helpers.end()) { auto helper = new JasonQt_InvokeFromThreadHelper; helper->moveToThread(thread); QObject::connect(thread, &QThread::finished, [=]() { g_mutex.lock(); auto it = g_helpers.find(thread); if(it != g_helpers.end()) { g_helpers.erase(it); } g_mutex.unlock(); }); g_helpers.insert( thread, helper ); it = g_helpers.find(thread); } it.value()->addCallback(callback); QMetaObject::invokeMethod(it.value(), "onRun", Qt::QueuedConnection); g_mutex.unlock();}void JasonQt_InvokeFromThread::waitForInvoke(QThread *thread, const std::function<void ()> &callback){ if(!(thread->isRunning())) { qDebug() << "JasonQt_InvokeFromThread::waitForInvoke: Target thread" << thread << "is not running!"; return; } g_mutex.lock(); auto it = g_helpers.find(thread); if(it == g_helpers.end()) { auto helper = new JasonQt_InvokeFromThreadHelper; helper->moveToThread(thread); QObject::connect(thread, &QThread::finished, [=]() { g_mutex.lock(); auto it = g_helpers.find(thread); if(it != g_helpers.end()) { g_helpers.erase(it); } g_mutex.unlock(); }); g_helpers.insert( thread, helper ); it = g_helpers.find(thread); } it.value()->addCallback([&]() { g_mutex.unlock(); callback(); }); QMetaObject::invokeMethod(it.value(), "onRun", Qt::QueuedConnection); g_mutex.lock(); g_mutex.unlock();}
测试代码:
int main(int argc, char *argv[]){ QCoreApplication a(argc, argv); qDebug() << "Main thread:" << QThread::currentThread(); constexpr auto threadCount = 5; QVector< QObject * > objects; QThreadPool threadPool; objects.resize(threadCount); threadPool.setMaxThreadCount(threadCount); for(auto i = 0; i < threadCount; i++) { QtConcurrent::run([&objects, i]() { objects[i] = new QObject; qDebug() << "Thread started:" << QThread::currentThread(); QEventLoop().exec(); }); } // 等待测试线程启动 QThread::sleep(3); // 调用 for(auto i = 0; i < (threadCount * 2); i++) { // 第一个参数是目标线程,第二个是回调 JasonQt_InvokeFromThread::invoke(objects[i % threadCount]->thread(), [=]() { qDebug() << "Current thread:" << QThread::currentThread() << ", Flag:" << i; }); } return a.exec();}
执行输出
Main thread: QThread(0x7f821951bf30)Thread started: QThread(0x7f8219705ac0, name = "Thread (pooled)")Thread started: QThread(0x7f8219705f90, name = "Thread (pooled)")Thread started: QThread(0x7f82197055f0, name = "Thread (pooled)")Thread started: QThread(0x7f8219705120, name = "Thread (pooled)")Thread started: QThread(0x7f8219704950, name = "Thread (pooled)")Current thread: QThread(0x7f8219704950, name = "Thread (pooled)") , Flag: 0Current thread: QThread(0x7f8219705ac0, name = "Thread (pooled)") , Flag: 3Current thread: QThread(0x7f8219705120, name = "Thread (pooled)") , Flag: 1Current thread: QThread(0x7f82197055f0, name = "Thread (pooled)") , Flag: 2Current thread: QThread(0x7f8219705f90, name = "Thread (pooled)") , Flag: 4Current thread: QThread(0x7f8219704950, name = "Thread (pooled)") , Flag: 5Current thread: QThread(0x7f8219705ac0, name = "Thread (pooled)") , Flag: 8Current thread: QThread(0x7f8219705120, name = "Thread (pooled)") , Flag: 6Current thread: QThread(0x7f8219705f90, name = "Thread (pooled)") , Flag: 9Current thread: QThread(0x7f82197055f0, name = "Thread (pooled)") , Flag: 7
可以看见,回调被执行在了测试线程中。
注:目标线程需要有运行Qt的事件循环,这是必须的。
0 0
- Qt:让任意线程执行一个匿名函数
- Qt 创建一个线程执行某个函数
- 利用QT的QThread将一个类中的成员函数转到线程下执行
- JS执行匿名函数
- 匿名自执行函数
- 自执行匿名函数
- 自执行匿名函数
- 匿名函数自执行
- 匿名函数自执行
- 自执行匿名函数
- Qt多线程编程中的对象线程与函数执行线程
- Qt多线程编程中的对象线程与函数执行线程
- Qt多线程编程中的对象线程与函数执行线程
- Qt多线程编程中的对象线程与函数执行线程
- Qt多线程编程中的对象线程与函数执行线程
- Qt 多线程编程中的对象线程与函数执行线程
- Qt多线程编程中的对象线程与函数执行线程
- Qt多线程编程中的对象线程与函数执行线程
- 《树状数组》hdu acm 5.3.2 一维
- 组合c(m,n)的计算方法
- 【图项目3—图的遍历——第12周】
- ViewGroup事件分发机制
- ViewPager+Fragment连用取消预加载(ViewPagerIndicator+Fragment)
- Qt:让任意线程执行一个匿名函数
- poj2553The Bottom of a Graph【scc+缩点】
- 关于thinkphp中自带的分页类中setConfig("last","尾页")无效的解决方法
- myeclipse中自动提示的设置
- Ubuntu 14.04 caffe 配置
- “Could not launch 'app name'”
- C#操作字符串方法总结<转>
- uva 839
- android studio 以及intellij idea 常用插件