首先,主类对象中,通过循环,创建最多20个进程,每个进程都会向主类进程返回字串,并且根据通过返回的字符串对进程进行相应的管理,比如,kill()及close(),两个函数位于接受消息函数中资信。接受消息函数通过readyReadStandardOutput()信号触发。问题是,这个消息处理函数中,在20多个进程同时返回消息的时候,在一些配置比较低的电脑中,会造成卡顿,所以考虑放进进程中进行处理。
因为在消息处理函数中,还需要使用到主进程中的其他的对象,比如QTextBrower,QLineEdit对象,如果使用这两种方法,目前我没有想到实现的方法。
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);
}
}
代码的说明: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创建的线程中,会出现改错误。