Название: setProperty из потока
Отправлено: fuCtor от Март 16, 2009, 14:13
Пытаюсь сделать "прозрачную" обработку изменений свойств объекта через обработку эвента о смене свойства (setProperty & QDynamicPropertyChangeEvent) , чтобы потом обработать это изменение. Но возникла проблема, при изменении приложение валится: --------------------------- Microsoft Visual C++ Debug Library --------------------------- Debug Error!
Program: f:\project\QAgent\Debug\QAgent.exe Module: 4.4.1 File: global\qglobal.cpp Line: 2027
ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 1ef7b8. Receiver '' (of type 'AAbstractAgent') was created in thread 975aa0", file kernel\qcoreapplication.cpp, line 280
(Press Retry to debug the application) --------------------------- Прервать Повтор Пропустить ---------------------------
Допустимо ли отправка эвента из потока, и можно ли как-нибудь иначе сделать задуманное?
Название: Re: setProperty из потока
Отправлено: pastor от Март 16, 2009, 14:38
покажи код
Название: Re: setProperty из потока
Отправлено: fuCtor от Март 16, 2009, 15:47
C++ (Qt) //------ aabstractagent.cpp -------------- #include "aabstractagent.h" #include "aabstracttransport.h" AAbstractAgent::AAbstractAgent(QObject *parent) : QThread(parent),running(false) { } AAbstractAgent::~AAbstractAgent() { running=false; wait(); } AAbstractTransport & AAbstractAgent::getTransport(){ return *transport; } void setTransport(AAbstractTransport* value){ } QTime AAbstractAgent::promoteTime(int step ){ paramManager.promoteTime(currentTime); currentTime.addSecs(step); if(currentTime > paramManager.getHorizont()) exec(); return currentTime; } void AAbstractAgent::sendNewState(QString paramName){ } QTime AAbstractAgent::getCurrentTime(){ return currentTime; } void AAbstractAgent::changedHorizont(QTime){ if(currentTime < paramManager.getHorizont()) QThread::quit(); } void AAbstractAgent::run(){ while(running) { sleep(1); body(); } } void AAbstractAgent::stop(){ QThread::quit(); running=false; } void AAbstractAgent::start(){ running=true; QThread::start(); } bool AAbstractAgent::isRunning(){ return running; } bool AAbstractAgent::eventFilter ( QObject * watched, QEvent * event ){ if(event->type() == QEvent::DynamicPropertyChange) { //Тут точка останова return QThread::eventFilter(watched,event); } else { return QThread::eventFilter(watched,event); } } //------ main.cpp -------------- #include <QtCore/QCoreApplication> #include "aabstractagent.h" class Agent: public AAbstractAgent { Q_PROPERTY(int counter READ getCounter WRITE setCounter) public: Agent(QObject * parent = 0):AAbstractAgent(parent){}; ~Agent(){}; int getCounter(){return counter;}; void setCounter(int val){ QCoreApplication::sendEvent(this, &QEvent(QEvent::DynamicPropertyChange)); //Iavnii vizov counter = val; }; void body(){ //setProperty("counter", getCounter()+1); //gluboko vnutri Qt setCounter(getCounter()+1); }; private: int counter; }; int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); Agent agent1; Agent agent2; agent1.start(); agent2.start(); return app.exec(); }
Код тестовый, не до конца допилиный и дописанный.
Название: Re: setProperty из потока
Отправлено: shadone от Март 18, 2009, 13:35
C++ (Qt) //------ aabstractagent.cpp -------------- #include "aabstractagent.h" #include "aabstracttransport.h" AAbstractAgent::AAbstractAgent(QObject *parent) : QThread(parent),running(false) { } AAbstractAgent::~AAbstractAgent() { running=false; wait(); } AAbstractTransport & AAbstractAgent::getTransport(){ return *transport; } void setTransport(AAbstractTransport* value){ } QTime AAbstractAgent::promoteTime(int step ){ paramManager.promoteTime(currentTime); currentTime.addSecs(step); if(currentTime > paramManager.getHorizont()) exec(); return currentTime; } void AAbstractAgent::sendNewState(QString paramName){ } QTime AAbstractAgent::getCurrentTime(){ return currentTime; } void AAbstractAgent::changedHorizont(QTime){ if(currentTime < paramManager.getHorizont()) QThread::quit(); } void AAbstractAgent::run(){ while(running) { sleep(1); body(); } } void AAbstractAgent::stop(){ QThread::quit(); running=false; } void AAbstractAgent::start(){ running=true; QThread::start(); } bool AAbstractAgent::isRunning(){ return running; } bool AAbstractAgent::eventFilter ( QObject * watched, QEvent * event ){ if(event->type() == QEvent::DynamicPropertyChange) { //Тут точка останова return QThread::eventFilter(watched,event); } else { return QThread::eventFilter(watched,event); } } //------ main.cpp -------------- #include <QtCore/QCoreApplication> #include "aabstractagent.h" class Agent: public AAbstractAgent { Q_PROPERTY(int counter READ getCounter WRITE setCounter) public: Agent(QObject * parent = 0):AAbstractAgent(parent){}; ~Agent(){}; int getCounter(){return counter;}; void setCounter(int val){ QCoreApplication::sendEvent(this, &QEvent(QEvent::DynamicPropertyChange)); //Iavnii vizov counter = val; }; void body(){ //setProperty("counter", getCounter()+1); //gluboko vnutri Qt setCounter(getCounter()+1); }; private: int counter; }; int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); Agent agent1; Agent agent2; agent1.start(); agent2.start(); return app.exec(); }
Код тестовый, не до конца допилиный и дописанный. в приведенном коде не хватает кода установки фильтра - непонятно кто чьи события фильтрует. Вообще говоря фильтровать события объектов из другого потока нужно очень осторожно, с использованием объектов синхронизации. Кстати вот этот код выглядит подозрительно: C++ (Qt) QCoreApplication::sendEvent(this, &QEvent(QEvent::DynamicPropertyChange));
по идее он должен работать без проблем - вроде бы временный объект создается и передается корректно - внутри точки следования, но выглядит опасно на мой взгляд. а по поводу ошибки в оригинальном сообщении - ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 1ef7b8. Receiver '' (of type 'AAbstractAgent') was created in thread 975aa0", file kernel\qcoreapplication.cpp, line 280 все просто - отправлять синхронное события между потоками нельзя - вместо этого нужно использовать postEvent для отправки асинхронного события.
Название: Re: setProperty из потока
Отправлено: fuCtor от Март 21, 2009, 09:59
все просто - отправлять синхронное события между потоками нельзя - вместо этого нужно использовать postEvent для отправки асинхронного события. В том то и загвоздка, что внутри Qt-а механизм оповещения о смене свойства реализован через sendEvent, а не через postEvent
|