Название: Сегментация при удалении сокета в потоке
Отправлено: Fregloin от Сентябрь 22, 2011, 10:07
Есть сокет class QCanSocket : public QObject { Q_OBJECT
QTcpSocket * fsocket; QTimer * ftimer; QString fhost; quint16 fport; bool freconnect;
int freconnectTimerId; void timerEvent(QTimerEvent *);
CCanQueue * fqueue;
public:
explicit QCanSocket(QObject *parent = 0); ~QCanSocket();
void moveToThread(QThread *thread);
quint16 port() const; QString host() const;
signals:
void sigPacketDataReceived(); void sigConnected(); void sigDisconnected(); void sigError(QAbstractSocket::SocketError socketError);
public slots:
void start(); void stop();
private slots:
void dataReady(); void connectedToServer(); void disconnectedFromServer(); void sendRequest(); void socketError(QAbstractSocket::SocketError socketError);
};
QCanSocket::QCanSocket(QObject *parent) : QObject(parent) { fhost = "192.168.1.33"; fport = 10003; fsocket = new QTcpSocket(); ftimer = new QTimer(); connect(fsocket,SIGNAL(connected()),this,SLOT(connectedToServer())); connect(fsocket,SIGNAL(disconnected()),this,SLOT(disconnectedFromServer())); connect(fsocket,SIGNAL(readyRead()),this,SLOT(dataReady())); connect(fsocket,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(disconnectedFromServer())); connect(ftimer,SIGNAL(timeout()),this,SLOT(sendRequest())); freconnect = false; freconnectTimerId = -1; fbufferSize = 4096; fsocket->setReadBufferSize(fbufferSize); fconnected = false; }
QCanSocket::~QCanSocket() { stop(); delete ftimer; delete fsocket; delete fbuffer; }
void QCanSocket::moveToThread(QThread *thread) { QObject::moveToThread(thread); fsocket->moveToThread(thread); ftimer->moveToThread(thread); }
void QCanSocket::connectedToServer() { emit sigConnected(); }
void QCanSocket::disconnectedFromServer() { emit sigDisconnected(); if(freconnect) { freconnectTimerId = startTimer(2000); } }
void QCanSocket::socketError(QAbstractSocket::SocketError socketError) { emit sigError(socketError); if(freconnect) { freconnectTimerId = startTimer(2000); } }
void QCanSocket::timerEvent(QTimerEvent * event) { if(freconnectTimerId==event->timerId()) { killTimer(event->timerId()); fsocket->connectToHost(fhost,fport); freconnectTimerId = -1; } }
void QCanSocket::start() { freconnect = true; if(fsocket->state()==QAbstractSocket::UnconnectedState) { fsocket->connectToHost(fhost,fport); } }
void QCanSocket::stop() { freconnect = false; if(fsocket->state()==QAbstractSocket::ConnectedState) { fsocket->disconnectFromHost(); } }
Есть поток, в котором создается сокет. class QCanThread : public QThread { Q_OBJECT
QCanSocket * fcanSocket;
public:
explicit QCanThread(QObject *parent = 0); ~QCanThread(); void run();
QCanSocket * canSocket() const {return fcanSocket;}
signals:
void sigConnected(); void sigDisconnected();
public slots:
void onTerminate();
};
QCanThread::QCanThread(QObject *parent) : QThread(parent) { /* connect(this,SIGNAL(terminated()),this,SLOT(onTerminate())); connect(this,SIGNAL(finished()),this,SLOT(onTerminate())); */ fcanSocket = new QCanSocket(); fcanSocket->moveToThread(this); }
void QCanThread::run() { fcanSocket->start(); exec(); }
QCanThread::~QCanThread() { delete fcanSocket; }
void QCanThread::onTerminate() { disconnect(fcanSocket,SIGNAL(sigPacketDataReceived())); }
Вот кусок когда в главном потоке, создание и удаления соединения void CArmDspLogic::connectToServer() { if(!fcanThread) { fcanThread = new QCanThread; fproject->fieldContainer()->canParser()->setCanSocket(fcanThread->canSocket()); connect(fcanThread->canSocket(),SIGNAL(sigConnected()),this,SLOT(connectedToServer())); connect(fcanThread->canSocket(),SIGNAL(sigDisconnected()),this,SLOT(disconnectedToServer())); fcanThread->start(); } }
void CArmDspLogic::disconnectFromServer() { if(fcanThread) { fproject->fieldContainer()->canParser()->setCanSocket(NULL); fcanThread->quit(); fcanThread->wait(); delete fcanThread; fcanThread = NULL; } }
void CArmDspLogic::connectedToServer() { fconnLabel->setText(trUtf8("Подключён")); }
void CArmDspLogic::disconnectedToServer() { fconnLabel->setText(trUtf8("Отключён")); }
При вызове disconnectFromServer программа вылетает с сообщением: ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread bff9850. Receiver '' (of type 'QNativeSocketEngine') was created in thread 11b3d718", file c:\ndk_buildrepos\qt-desktop\src\corelib\kernel\qcoreapplication.cpp, line 349 Invalid parameter passed to C runtime function. Invalid parameter passed to C runtime function.
Если же сделать QCanThread::~QCanThread() { //delete fcanSocket; //закоментируем удаление сокета в деструктрое программы }
то програ не вылетает, но и не вызывается деструктор сокета. В чем проблема?
Название: Re: Сегментация при удалении сокета в потоке
Отправлено: Пантер от Сентябрь 22, 2011, 10:22
Лень читать код, но думаю, deleteLater тебе поможет.
Название: Re: Сегментация при удалении сокета в потоке
Отправлено: Fregloin от Сентябрь 22, 2011, 10:33
deleteLater применять к сокету или потоку?
Название: Re: Сегментация при удалении сокета в потоке
Отправлено: Пантер от Сентябрь 22, 2011, 10:36
К сокету. delete fcanSocket -> fcanSocket->deleteLater ()
Название: Re: Сегментация при удалении сокета в потоке
Отправлено: Fregloin от Сентябрь 22, 2011, 10:37
так и сделал, теперь при вызове disconnectFormServer получаю QThread: Destroyed while thread is still running
Название: Re: Сегментация при удалении сокета в потоке
Отправлено: andrew.k от Сентябрь 22, 2011, 13:47
Думаю проблема в этих коннектах. connect(fsocket,SIGNAL(connected()),this,SLOT(connectedToServer())); connect(fsocket,SIGNAL(disconnected()),this,SLOT(disconnectedFromServer())); connect(fsocket,SIGNAL(readyRead()),this,SLOT(dataReady())); connect(fsocket,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(disconnectedFromServer())); connect(ftimer,SIGNAL(timeout()),this,SLOT(sendRequest())); Конструктор работает в другом потоке, отличном от потока в котором потом все работать будет. Хотя возможно, moveToThread исправляет это дело. Но мне кажется все таки лучше connect делать в run () потока. Плюс ты в конструкторе создаешь fsocket = new QTcpSocket(); и другие. Создавай их в run и не придется делать moveToThread.
Название: Re: Сегментация при удалении сокета в потоке
Отправлено: Fregloin от Сентябрь 22, 2011, 16:19
а как мне тогда обращаться к сокету из других потоков?
Название: Re: Сегментация при удалении сокета в потоке
Отправлено: andrew.k от Сентябрь 26, 2011, 11:44
а как мне тогда обращаться к сокету из других потоков?
А в чем проблема?
Название: Re: Сегментация при удалении сокета в потоке
Отправлено: andrew.k от Сентябрь 26, 2011, 11:45
Я ни в коем случае не говорю, что коннекты надо убрать. Их нужно переместить в run и там же создавать экземпляр QSocket.
|