| 
 Название: 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
 
 |