【发布时间】:2014-04-17 09:15:07
【问题描述】:
我编写了一个 QT - webkit 应用程序。当我的 pSeudo 驱动程序获取字符“l”时,此应用程序会触发回调。但是,应用程序在回调期间崩溃 - 它说 - QObject::setParent: 无法设置父级,新父级在不同的线程中。我不知道要解决这个问题,我尝试做 moveToThread,但它没有帮助。请在这里帮助我。
#include <QtGui/QApplication>
#include <QApplication>
#include <QDebug>
#include <QWebFrame>
#include <QWebPage>
#include <QWebView>
#include <QThread>
#include <unistd.h>
#include <fcntl.h>
class DemoThread;
class MyJavaScriptOperations : public QObject {
Q_OBJECT
public:
QWebView *view;
DemoThread *m_pDemoThread;
MyJavaScriptOperations();
void firecb();
bool slot_installed;
signals:
void alert_script_signal();
public slots:
void JS_ADDED();
void loadFinished(bool);
private:
};
class DemoThread : public QThread {
public:
DemoThread( MyJavaScriptOperations *pJavascriptOp);
protected:
void run();
private :
MyJavaScriptOperations *m_pJavascriptOp;
};
DemoThread::DemoThread(MyJavaScriptOperations *pJavascriptOp):m_pJavascriptOp(pJavascriptOp)
{
}
void DemoThread:: run()
{
int filedesc = open("/dev/pSeudoDrv", O_RDONLY);
if(filedesc < 0)
{
qDebug()<<"Couldn't open Driver.";
}
unsigned char buff;
while(1)
{
read(filedesc,&buff, 1);
qDebug()<<"The code received is "<< buff;
if ( (m_pJavascriptOp->slot_installed == true) && (buff == 166))
{
m_pJavascriptOp->firecb();
}
qDebug()<<"Running Thread.";
sleep(6);
}
}
void MyJavaScriptOperations::JS_ADDED()
{
qDebug()<<__PRETTY_FUNCTION__;
view->page()->mainFrame()->addToJavaScriptWindowObject("myoperations", this);
}
void MyJavaScriptOperations::loadFinished(bool oper)
{
qDebug()<<__PRETTY_FUNCTION__<< oper;
slot_installed = true;
// firecb();
}
void MyJavaScriptOperations::firecb()
{
qDebug()<<__PRETTY_FUNCTION__;
view->page()->mainFrame()->evaluateJavaScript("JavaScript_function()");
}
MyJavaScriptOperations::MyJavaScriptOperations()
{
qDebug()<<__PRETTY_FUNCTION__;
view = new QWebView();
view->resize(400, 500);
connect(view->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(JS_ADDED()));
connect(view, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished(bool)));
view->load(QUrl("./index.html"));
view->show();
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyJavaScriptOperations *jvs = new MyJavaScriptOperations;
DemoThread *thread = new DemoThread(jvs);
jvs->moveToThread(thread);
thread->start();
return a.exec();
}
#include "main.moc"
这是我得到的崩溃错误 -
./QT_DEMO
MyJavaScriptOperations::MyJavaScriptOperations()
loaded the Generic plugin
The code received is 156
Running Thread.
The code received is 166
void MyJavaScriptOperations::firecb()
QObject::setParent: Cannot set parent, new parent is in a different thread
【问题讨论】:
-
你正在做一些非常危险的事情。您正在从非 gui 线程执行 GUI 工作。您的
view对象应该存在于 GUI 线程中,但您正在从不同的线程访问它的函数,而这些函数不是线程安全的函数。您的线程中也没有运行事件循环,因此永远不会通过信号调用您的插槽。即使您确实运行了一个事件循环,您的while(1)循环也会阻止它。 -
read() 使其成为事件循环。
-
read()是否在呼叫QThread::exec()? -
我对事件循环的理解是会等待事件发生,直到任何事件发生才会阻塞。因此,我正在使用 read(),它将阻塞线程,直到读取检索到任何东西。我已经修复了崩溃。请看我的解决方案。请告诉我,如果有设计问题。顺便说一句,我的角色驱动程序在这里 - stackoverflow.com/questions/23133981/…。该功能有效,但问题是当我删除字符驱动程序时。我的系统崩溃了。
-
并且必须在某处输入事件循环。它不会自己神奇地做到这一点。当您调用
QApplication::exec时,即进入事件循环。当您调用进入事件循环的QThread::exec时。如果你想在你的线程中使用槽,你必须告诉你的线程进入事件循环。