• 把函数放在线程中执行碰到的问题及解决:


    技术背景:

    首先,主类对象中,通过循环,创建最多20个进程,每个进程都会向主类进程返回字串,并且根据通过返回的字符串对进程进行相应的管理,比如,kill()及close(),两个函数位于接受消息函数中资信。接受消息函数通过readyReadStandardOutput()信号触发。问题是,这个消息处理函数中,在20多个进程同时返回消息的时候,在一些配置比较低的电脑中,会造成卡顿,所以考虑放进进程中进行处理。

    在这个项目环境下,不考虑继承QObject使用movetoThread()和继承QThread直接重写run()的方法,理由:

    因为在消息处理函数中,还需要使用到主进程中的其他的对象,比如QTextBrower,QLineEdit对象,如果使用这两种方法,目前我没有想到实现的方法。

    所以考虑使用QFuture+QtConcurrent的形式,具体使用:

    bool state = false;
        qRegisterMetaType<QTextCursor>("QTextCursor");
        QFuture<void> future = QtConcurrent::run(this, &run_bank::ReadData, sender(),state);
        while (!future.isFinished()) {
            QCoreApplication::processEvents();
        }
        if(state == true)
        {
            ((QProcess *)sender())->close();
            ((QProcess *)sender())->kill();
            if(((QProcess *)sender())->isOpen())
            {
                QMessageBox::information(this, "提示信息", "脚本还未正常关闭",QMessageBox::Yes, QMessageBox::Yes);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    代码的说明:state是记录ReadData函数中处理得出的是否需要清楚进程的标志位。
    之所以注册QTextCursor,是因为进程之间会使用到这个类型作为数据传输。这个传输是我使用的QTextEdit等对象中隐藏的,当我们通过QtConcurrent把函数放到单独的一个线程的时候,因为第三行的写法是执行的类中的方法,所以还是可以直接使用对象的,但是需要传递到主进程中,已经隐藏了数据传递过程。

    出现的几个问题:

    QObject::startTimer: Timers cannot be started from another thread
    网上资料:每个QObject实例中,接受信号或者事件时,槽函数或者事件处理器将在对象所处的线程中执行。然后这个定时器是在线程类的构造函数中,我们在主进程中创建了一个对象,所以定时器是在主进程中的,而start()在线程中调用,所以会报错。
    解决这个问题的方法:
    1、在TestThread线程启动后创建定时器:线程在主进程中实例化,他的子对象也需要在主进程里创建,不能指定定时器的福对象为子线程。使用事件循环exec(),否则线程也会立即结束,并发出finished()信号。stop()也需要在线程中调用。
    2、在主进程中创建,然后使用movetoThread()方法改变定时器多出的线程,不要给定时器设置父类,否则该函数将不会生效。
    我使用的方法是第二种,直接QTimer *timer = new QTimer();不要继承this就行。

    一般都不要继承this,否则我们在子进程或是什么定位设置了一个禁止接受消息,就会卡顿到timeout()信号,就会出问题。

    QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread
    出现这个问题主要就是因为if(state == true)之后的代码段,之前我的if函数体是放在QtConcurrent(线程安全)开启的单独线程中的,和主线程是不相关的,所以在QtConcurrent创建的线程中,会出现改错误。

  • 相关阅读:
    抓包神器TCPDUMP的分析总结-涵盖各大使用场景、高级用法
    理解RESTful Api设计
    瀑布流布局
    直播课堂系统08补-腾讯云对象存储和课程分类管理
    解码2022中国网安强星丨“老兵”的热爱与坚持,绿盟科技在网络安全时代里奔赴成长
    【必看技巧】Access开发者必备:如何用代码隐藏功能区、导航区、状态栏?
    postman——集合——执行集合——测试脚本——pm对象简单示例02
    js中的基础知识点
    背会了常见的几个线程池用法,结果被问翻了
    人工智能基础 | 回归分析(四)
  • 原文地址:https://blog.csdn.net/qq_31749395/article/details/127597037