当前位置: 首页 > news >正文

asp.net网站模板免费下载文化共享工程网站建设情况

asp.net网站模板免费下载,文化共享工程网站建设情况,软件技术专科生的出路,推广软件排行榜前十名引用 Qt多线程中使用QTimer#xff08;常见问题汇总#xff09; [多线程]多线程使用QTimer Qt::ConnectionType#xff1a;Qt不同类型connect的详细区别说明与应用 Qt的4种多线程实现方式 一文搞定之Qt多线程(QThread、moveToThread) QTimer The QTimer class provides repe…引用 Qt多线程中使用QTimer常见问题汇总 [多线程]多线程使用QTimer Qt::ConnectionTypeQt不同类型connect的详细区别说明与应用 Qt的4种多线程实现方式 一文搞定之Qt多线程(QThread、moveToThread) QTimer The QTimer class provides repetitive and single-shot timers. The QTimer class provides a high-level programming interface for timers. To use it, create a QTimer, connect its timeout() signal to the appropriate slots, and call start(). From then on, it will emit the timeout() signal at constant intervals. 使用QTimer类定义一个定时器它可以不停重复也可以只进行一次便停止 QTimer *timer new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(update())); timer-start(1000);创建一个QTimer对象将信号timeout()与相应的槽函数相连然后调用start()函数。接下来每隔一段时间定时器便会发出一次timeout()信号 Qt多线程的实现 QThread::run() QThread 是 Qt 中实现多线程的基础类通过继承 QThread 类并重写其 run() 函数可以实现自定义线程逻辑 线程类 #ifndef WORKER_H #define WORKER_H#include QThreadclass Worker : public QThread { public:Worker();void run();void printFunc();};#endif // WORKER_H#include Worker.h #include QDebugWorker::Worker() {}void Worker::run() {qDebug()子线程ThreadID: QThread::currentThreadId(); }void Worker::printFunc() {qDebug()子线程成员函数ThreadID: QThread::currentThreadId(); }main函数 #include iostream #include QDebug #include Worker.husing namespace std;int main() {Worker w;w.start();qDebug()主线程ThreadID: QThread::currentThreadId();w.printFunc();while (1){}return 0; }执行结果 子线程ThreadID: 0x4138 主线程ThreadID: 0x34b0 子线程成员函数ThreadID: 0x34b0主线程和子线程执行的顺序不确定偶尔主线程在前偶尔子线程在前 子线程类的成员函数包括槽函数是运行在主线程当中的只有run()函数运行在子线程中 如果在run()函数中调用子线程类成员函数那么该成员函数运行在子线程中 在run()函数中调用子线程成员函数 #include Worker.h #include QDebugWorker::Worker() {}void Worker::run() {qDebug()子线程ThreadID: QThread::currentThreadId();printFunc(); }void Worker::printFunc() {qDebug()子线程成员函数ThreadID: QThread::currentThreadId(); // emit doTask(); }主线程ThreadID: 0x2140 子线程ThreadID: 0x2044 子线程成员函数ThreadID: 0x2044QThread::moveToThread() moveToThread() 是 Qt 中用于将对象移动到另一个线程的方法。通过调用 moveToThread() 函数可以将一个 QObject 对象从当前线程移动到另一个线程中从而实现对象在新线程中执行特定的任务 在多线程编程中通常会使用 moveToThread() 方法来将耗时的任务或需要在单独线程中执行的逻辑移动到单独的线程中以避免阻塞主线程通常是 GUI 线程的执行 线程类 #ifndef WORKER_H #define WORKER_H#include QObjectclass Worker : public QObject {Q_OBJECT public:Worker();void printFunc();public slots:void doWork();void doWork2();void doWork3();signals:void testdoWork3();};#endif // WORKER_H#include Worker.h #include QDebug #include QThreadWorker::Worker() {}void Worker::printFunc() {qDebug() 成员函数ThreadID:QThread::currentThreadId();}void Worker::doWork() {qDebug() doWork ThreadID:QThread::currentThreadId(); }void Worker::doWork2() {qDebug() doWork2 ThreadID:QThread::currentThreadId(); }void Worker::doWork3() {qDebug() doWork3 ThreadID:QThread::currentThreadId(); }main函数 #include mainwindow.h#include QApplication #include Worker.h #include QDebug #include QThreadint main(int argc, char *argv[]) {QApplication a(argc, argv);//MainWindow w;//w.show();Worker worker;QThread thread;worker.moveToThread(thread);QObject::connect(thread, QThread::started, worker, Worker::doWork); //第一槽函数QObject::connect(thread, QThread::started, worker, Worker::doWork2); //第二槽函数QObject::connect(worker, Worker::testdoWork3, worker, Worker::doWork3); //第三槽函数//启动线程thread.start();//调用成员数worker.printFunc();//发送自定义信号emit worker.testdoWork3();while (1) {}return a.exec(); }执行结果 成员函数ThreadID: 0x1330 doWork ThreadID: 0x4070 doWork2 ThreadID: 0x4070 doWork3 ThreadID: 0x4070槽函数无论是线程的信号触发还是自定义信号触发槽函数都在新线程里运行 成员函数和主函数运行在主线程当中 QtConcurrent::run() QtConcurrent::run 是 Qt 库中的一个用于并行执行任务的函数。它允许你在一个独立的线程中运行一个函数而无需显式地创建和管理线程。这是通过将函数和其参数传递给 QtConcurrent::run 来实现的Qt 会自动管理线程池和线程的生命周期 QtConcurrent::run能够方便快捷的将任务丢到子线程中去执行无需继承任何类也不需要重写函数使用非常简单。需要注意的是由于该线程取自全局线程池QThreadPool函数不能立马执行需要等待线程可用时才会运行 使用QtConcurrent::run()的基本步骤 传递一个函数或可调用对象例如 lambda、函数指针、成员函数等给 QtConcurrent::runQtConcurrent::run 会在后台线程中执行该函数并返回一个 QFuture 对象表示异步操作的结果可以通过 QFuture 来监控任务的进度和结果 基本语法 QFutureTResult QtConcurrent::run(Func func, Args... args);func要执行的函数或可调用对象args传递给函数的参数 #include QCoreApplication #include QtConcurrent #include QDebug #include QThread #include QFuturevoid slowFunction(int seconds) {qDebug() Start slow function in thread: QThread::currentThreadId();QThread::sleep(seconds); // 模拟耗时操作qDebug() Finished slow function; }int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);// 在后台线程执行 slowFunctionQFuturevoid future QtConcurrent::run(slowFunction, 5); // 传入参数 5 表示等待 5 秒// 在此可以执行其他操作不会被阻塞qDebug() Main thread doing something else...;// 等待后台任务完成future.waitForFinished();return a.exec(); }QtConcurrent::run(slowFunction, 5) 会在后台线程中运行 slowFunction并传递参数 5该函数会使线程等待 5 秒钟在此过程中主线程可以继续执行其他任务比如打印 “Main thread doing something else…”。future.waitForFinished() 会阻塞主线程直到后台任务完成 如果任务有返回值可以通过 QFuture::result() 获取 #include QCoreApplication #include QtConcurrent #include QDebug #include QFutureint computeSum(int a, int b) {qDebug() Computing sum in background thread...;QThread::sleep(2); // 模拟耗时操作return a b; }int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);// 在后台线程中执行带有返回值的任务QFutureint future QtConcurrent::run(computeSum, 5, 10);// 在此可以继续执行其他任务qDebug() Main thread is free to do other work;// 获取任务的结果int result future.result(); // 阻塞直到任务完成qDebug() The result of computation is: result;return a.exec(); }如果需要在任务完成后处理结果可以使用 QFuture::watch() 或者 QFutureWatcher 来接收通知 QtConcurrent::run 是一个简单的 API它依赖于 Qt 的线程池来管理线程因此它适合处理不需要显式控制线程的简单任务 总结 moveToThread对比传统子类化Qthread更灵活仅需要把你想要执行的代码放到槽movetothread这个object到线程然后拿一个信号连接到这个槽就可以让这个槽函数在线程里执行。可以说movetothread给我们编写代码提供了新的思路当然不是说子类化QThread不好只是你应该知道还有这种方式去调用线程 轻量级的函数可以用movethread多个短小精悍能返回快速的线程函数适用 无需创建独立线程类例如你有20个小函数要在线程内做, 全部扔给一个QThread。而我觉得movetothread和子类化QThread的区别不大更可能是使用习惯引导。又或者你一开始没使用线程但是后边发觉这些代码还是放线程比较好如果用子类化QThread的方法重新设计代码将会有可能让你把这一段推到重来这个时候moveThread的好处就来了你可以把这段代码的从属着movetothread把代码移到槽函数用信号触发它就行了。其它的话movetothread它的效果和子类化QThread的效果是一样的槽就相当于你的run()函数你往run()里塞什么代码就可以往槽里塞什么代码子类化QThread的线程只可以有一个入口就是run()而movetothread就有很多触发的入口 以下是一些常用的QThread函数 start(): 启动线程使线程进入运行状态调用线程的run()方法run(): 线程的执行函数需要在该函数中编写线程所需执行的任务quit(): 终止线程的事件循环在下一个事件处理周期结束时退出线程wait(): 阻塞当前线程直到线程执行完成或超时finished(): 在线程执行完成时发出信号terminate(): 强制终止线程的执行不推荐使用可能导致资源泄漏和未定义行为isRunning(): 判断线程是否正在运行currentThreadId(): 返回当前线程的IDyieldCurrentThread(): 释放当前线程的时间片允许其他线程执行setPriority(): 设置线程优先级msleep(): 让当前线程休眠指定的毫秒数 函数使用时的注意事项 start()函数: 调用start()函数启动线程时会自动调用线程对象的run()方法。不要直接调用run()方法来启动线程应该使用start()函数wait()函数: wait()函数会阻塞当前线程直到线程执行完成。在调用wait()函数时需要确保不会发生死锁的情况避免主线程和子线程相互等待对方执行完成而无法继续terminate()函数: 调用terminate()函数会强制终止线程这样可能会导致资源未能正确释放造成内存泄漏等问题。因此应该尽量避免使用terminate()函数而是通过设置标志让线程自行退出quit()函数: quit()函数用于终止线程的事件循环通常与exec()函数一起使用。在需要结束线程事件循环时可以调用quit()函数finished信号: 当线程执行完成时会发出finished信号可以连接这个信号来处理线程执行完成后的操作yieldCurrentThread()函数: yieldCurrentThread()函数用于让当前线程让出时间片让其他线程有机会执行。使用时应该注意避免过多的调用否则会影响程序性能 多线程中的QTimer 错误用法 错误用法1 子类化QThread在线程类中定义一个定时器然后在run()方法中调用定时器的start()方法 TestThread::TestThread(QObject *parent): QThread(parent) {m_pTimer new QTimer(this);connect(m_pTimer, QTimer::timeout, this, TestThread::timeoutSlot); }void TestThread::run() {m_pTimer-start(1000); }void TestThread::timeoutSlot() {qDebug() QString::fromLocal8Bit(当前线程id) QThread::currentThread(); }接下来在主线程中创建该线程对象并调用它的start()方法 m_pThread new TestThread(this); m_pThread-start();执行时会报错定时器不能被其它线程start QObject::startTimer: Timers cannot be started from another thread分析一下 刚开始只有主线程一个TestThread的实例是在主线程中创建的定时器在TestThread的构造函数中所以也是在主线程中创建的当调用TestThread的start()方法时这时有两个线程。定时器的start()方法是在另一个线程中也就是TestThread中调用的 创建和调用并不是在同一线程中所以出现了错误 每个QObject实例都有一个叫做“线程关系”(thread affinity)的属性或者说它处于某个线程中。默认情况下QObject处于创建它的线程中。 当QObject接收队列信号(queued signal)或者传来的事件(posted event)槽函数或事件处理器将在对象所处的线程中执行。 根据以上的原理Qt使用计时器的线程关系(thread affinity)来决定由哪个线程发出timeout()信号。正因如此你必须在它所处的线程中start或stop该定时器在其它线程中启动定时器是不可能的。 错误用法2 OK看完错误1那是不是在run函数里面构造定时器就可以了构造也要小心喔别一不小心指定了父类如下 void MyThread::run() {timer new QTimer(this);connect(timer,SIGNAL(timeout()),this,SLOT(timerOut()));timer-start(1000);exec(); }执行时报错 QObject: Cannot create children for a parent that is in a different thread. (Parent is TestThread(0x709d88), parent’s thread is QThread(0x6e8be8), current thread is TestThread(0x709d88)因为TestThread对象是在主线程中创建的它的QObject子对象也必须在主线程中创建。所以不能指定父对象为TestThread 错误用法3 这个问题也很容易犯即计时器虽在线程中初始化但在子线程非run()函数中开始start() void MyThread::run() {timer new QTimer();connect(timer,SIGNAL(timeout()),this,SLOT(timerOut()));startTimer();exec(); }void MyThread::startTimer(){qDebug()当前线程ID:QThread::currentThreadId();timer-start(1000); }void MyThread::timerOut() {qDebug()当前线程ID:QThread::currentThreadId(); }执行输出 前线程ID: 0x4338 当前线程ID: 0x3e20 当前线程ID: 0x3e20run()函数线程为子线程因此run函数中运行startTimer()为run所处线程但因为startTimer()初始化时为主线程因此timer-start()也随之在主线程中开始计时器槽函数也在主线程中运行 正确用法 正确用法1 void MyThread::run() {timer new QTimer();connect(timer,SIGNAL(timeout()),this,SLOT(timerOut()));timer-start(1000);exec(); }void MyThread::timerOut() {qDebug()当前线程ID:QThread::currentThreadId(); }执行输出 主线程ID: 0x4458 当前线程ID: 0x4094 当前线程ID: 0x4094 当前线程ID: 0x4094正确用法2 无需子类化线程类通过信号启动定时器 TestClass::TestClass(QWidget *parent): QWidget(parent) {m_pThread new QThread(this);m_pTimer new QTimer();m_pTimer-moveToThread(m_pThread);m_pTimer-setInterval(1000);connect(m_pThread, SIGNAL(started()), m_pTimer, SLOT(start()));connect(m_pTimer, QTimer::timeout, this, ThreadTest::timeOutSlot, Qt::DirectConnection); } 通过moveToThread()方法改变定时器所处的线程不要给定时器设置父类否则该函数将不会生效 首先将定时器所处的线程改为新建的线程然后连接信号槽槽函数在定时器所处的线程中执行注意信号槽的连接类型为Qt::DirectConnection 正确用法3 如果不想在run()函数中就开始计时器而是在线程运行过程中根据实际情况开启之前错误3的情况时要怎么办呢 解决办法为信号与槽连接中使用Qt::*DirectConnection* 信号与槽连接默认方式为Qt::AutoConnection因此会根据函数所处的线程自动跳转导致错误3中的情况 void MyThread::run() {timer new QTimer();connect(timer,SIGNAL(timeout()),this,SLOT(timerOut()),Qt::DirectConnection);startTimer();exec(); }void MyThread::startTimer(){qDebug()当前线程ID:QThread::currentThreadId();timer-start(1000); }void MyThread::timerOut() {qDebug()当前线程ID:QThread::currentThreadId(); }执行输出 主线程ID: 0x4424 当前线程ID: 0x470c 当前线程ID: 0x470c 当前线程ID: 0x470c 当前线程ID: 0x470cQt::ConnectionType 从上面的内容可以看到又引申出了多线程中槽函数在哪个线程中执行的问题这里再补充说明下 同一对象的不同槽函数可以有不同的连接类型槽函数在哪个线程被执行由连接类型、信号发射时收发双方是否在一个线程决定 类型说明 Qt::AutoConnection 默认连接类型如果信号接收方与发送方在同一个线程则使用Qt::DirectConnection否则使用Qt::QueuedConnection连接类型在信号发射时决定 Qt::DirectConnection 信号所连接至的槽函数将会被立即执行并且是在发射信号的线程倘若槽函数执行的是耗时操作、信号由UI线程发射则会阻塞Qt的事件循环UI会进入无响应状态 Qt::QueuedConnection 槽函数将会在接收者的线程被执行此种连接类型下的信号倘若被多次触发、相应的槽函数会在接收者的线程里被顺次执行相应次数当使用QueuedConnection时参数类型必须是Qt基本类型或者使用qRegisterMetaType() 进行注册了的自定义类型 Qt::BlockingQueuedConnection 和Qt::QueuedConnection类似区别在于发送信号的线程在槽函数执行完毕之前一直处于阻塞状态收发双方必须不在同一线程否则会导致死锁 Qt::UniqueConnection 可以搭配以上所有连接类型使用一经设置之后同一信号与同一槽函数的二次连接将会失败 测试验证 #ifndef WIDGET_H #define WIDGET_H#include QWidget #include QThread #include QPushButton #include windows.hQT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass ThreadWorker : public QObject {Q_OBJECT public:ThreadWorker(QObject* parent);public slots:void queuedConnect();void directConnect(); };class Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);~Widget();private:QVectorQThread* listThread;QVectorThreadWorker* listWorker;Ui::Widget *ui;private slots:void on_butDirect_clicked();void on_butQueued_clicked();void on_butAuto_clicked();signals:void directConnect();void autoConnect();void queuedConnect();}; #endif // WIDGET_H#include widget.h #include ui_widget.h #include QDebugWidget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui-setupUi(this);for(int i 0 ; i 3 ; i){listThread.append(new QThread(this));listWorker.append(new ThreadWorker(nullptr));}connect(this,SIGNAL(directConnect()),listWorker[0],SLOT(directConnect()),Qt::DirectConnection);connect(this,SIGNAL(autoConnect()),listWorker[2],SLOT(directConnect()),Qt::AutoConnection);connect(this,SIGNAL(queuedConnect()),listWorker[1],SLOT(queuedConnect()),Qt::QueuedConnection);connect(this,SIGNAL(directConnect()),listWorker[1],SLOT(directConnect()),Qt::QueuedConnection);for(int i 0 ; i 3 ; i )listWorker[i]-moveToThread(listThread[i]);for(auto i : listThread) i-start();qDebug()The main thread id is QThread::currentThreadId();}Widget::~Widget() {delete ui;for(auto i : listThread)i-exit(); }void Widget::on_butDirect_clicked() {emit directConnect(); }void Widget::on_butQueued_clicked() {emit queuedConnect(); }void Widget::on_butAuto_clicked() {emit autoConnect();}ThreadWorker::ThreadWorker(QObject *parent) : QObject(parent) {}void ThreadWorker::queuedConnect() {for(int i 0 ; i 10 ; i )Sleep(100);qDebug()The kid thread id is QThread::currentThreadId();} void ThreadWorker::directConnect() {for(int i 0 ; i 10 ; i )Sleep(100);qDebug()The kid thread id is QThread::currentThreadId();}执行输出 The main thread id is 0x30b0 The kid thread id is 0x30b0 The kid thread id is 0x7cc The kid thread id is 0x7cc The kid thread id is 0x24c0小结 这里参考学习了多篇博客对Qt的多线程实现以及如何在多线程场景中使用QTimer有了更深的认识同时对多线程中槽函数的调用也有了新的认识。希望和大家一起进步
http://www.eeditor.cn/news/119658/

相关文章:

  • 郑州营销型网站推广工具专业瓷砖美缝网站怎么做
  • 百度网站管理员工具郑州网站设计的公司
  • 做搬家网站的素材汕头网站建设过程
  • 云南百度建站新密网站
  • 网站开发答辩演讲公司电子产品网站模板
  • 0基础多久学会网站架构石家庄市城乡和建设局网站
  • 遇到钓鱼网站怎么做长宁网站建设公司
  • 身高差效果图网站顺昌网站建设wzjseo
  • 西安公司网站设计温州市城市建设档案馆网站
  • 网站建设功能点价格建筑模板多少钱一张什么尺寸
  • 怎么做网站开发的方案网站引导动画怎么做的
  • 网站开发团队 分工门户网站建设项目书
  • 九里微网站开发关键词爱站网
  • app推荐网站重庆建设建设工程信息网站
  • 常州网站建设企业网站制作盐山国外网站建设
  • 网站留言效果怎么做美团初期是怎么建网站
  • 做网站挂广告赚多少钱erp管理系统软件有哪些
  • 电子商务网站建设的步骤一般为(wordpress圆角插件汉化
  • 怎么样建设网站网站厦门推广平台较好的
  • 高端企业网站设计公司网站建设与管理试卷_
  • 南昌品牌网站建设android编程语言
  • 哈尔滨网站建设与管理用tomcat做网站目录
  • 网站代运营合同模板免费ppt模板下载无水印
  • 网站建设维护合同模板大同网页设计
  • 高端模板网站建设网站规划书包括哪些方面
  • 百度调整导致网站排名下降最美情侣高清免费视频播放
  • 公司网站自己可以学习优化吗wordpress 时间标题展示
  • 加微信群网站怎么做的网站推广做多大尺寸
  • 在线制作h5网页seo的优化策略有哪些
  • 做推广哪个食品网站好wordpress 添加设置方法