Russian Qt Forum
Ноябрь 25, 2024, 15:29 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: setProperty из потока  (Прочитано 4960 раз)
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)
---------------------------
Прервать   Повтор   Пропустить   
---------------------------

Допустимо ли отправка эвента из потока, и можно ли как-нибудь иначе сделать задуманное?
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #1 : Март 16, 2009, 14:38 »

покажи код
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
fuCtor
Гость
« Ответ #2 : Март 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();
}
 

Код тестовый, не до конца допилиный и дописанный.
Записан
shadone
Гость
« Ответ #3 : Март 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 для отправки асинхронного события.
Записан
fuCtor
Гость
« Ответ #4 : Март 21, 2009, 09:59 »

Цитировать
все просто - отправлять синхронное события между потоками нельзя - вместо этого нужно использовать postEvent для отправки асинхронного события.
В том то и загвоздка, что внутри Qt-а механизм оповещения о смене свойства реализован через sendEvent, а не через postEvent
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.178 секунд. Запросов: 22.