Объявил следующий класс:
C++ (Qt)
class UnpProtocol : public QThread
{
Q_OBJECT
private slots:
void onThreadStop();
protected:
bool m_connected;
virtual void unpDisconnect();
virtual void unpConnect();
void run();
protected slots:
virtual void onTcpConnected();
virtual void onTcpDisconnected();
virtual void onTcpError(QAbstractSocket::SocketError);
public:
UnpProtocol();
~UnpProtocol();
signals:
void needRegistration();
void registrationResult(bool);
};
UnpProtocol::UnpProtocol() :
QThread(0)
{
this->moveToThread(this);
}
UnpProtocol::~UnpProtocol()
{
exit();
wait();
}
void UnpProtocol::run()
{
connect(fSocket, SIGNAL(connected()),
this, SLOT(onTcpConnected()));
connect(fSocket, SIGNAL(disconnected()),
this, SLOT(onTcpDisconnected()));
connect(fSocket, SIGNAL(readyRead()),
this, SLOT(onTcpReadyRead()));
connect(fSocket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(onTcpError(QAbstractSocket::SocketError)));
connect(this, SIGNAL(finished()),
SLOT(onThreadStop()));
unpConnect();
// unpDisconnect();
exec();
}
void UnpProtocol::unpConnect()
{
m_connected = false;
}
void UnpProtocol::unpDisconnect()
{
m_connected = false;
}
void UnpProtocol::onTcpDisconnected()
{
#ifdef QT_DEBUG
qDebug() << "Disconnet form address";
#endif
}
void UnpProtocol::onTcpConnected()
{
#ifdef QT_DEBUG
qDebug() << "Connected to address";
#endif
}
void UnpProtocol::onTcpError(QAbstractSocket::SocketError err)
{
#ifdef QT_DEBUG
QString strError =
"Error: " + (err == QAbstractSocket::HostNotFoundError ?
"The host was not found." :
err == QAbstractSocket::RemoteHostClosedError ?
"The remote host is closed." :
err == QAbstractSocket::ConnectionRefusedError ?
"The connection was refused." :
QString("other error - %1").arg(fSocket->errorString())
);
qDebug() << strError;
#endif
m_connected = false;
}
void UnpProtocol::onThreadStop()
{
if (m_connected)
unpDisconnect();
}
Объявил потомка
C++ (Qt)
class UnpClientProtocol: public UnpProtocol
{
Q_OBJECT
private:
bool selfDisconnect;
int timerId;
protected:
void unpConnect();
void unpDisconnect();
void run();
void timerEvent(QTimerEvent* event);
protected slots:
void onTcpConnected();
void onTcpDisconnected();
void onTcpError(QAbstractSocket::SocketError);
public:
UnpClientProtocol();
};
UnpClientProtocol::UnpClientProtocol() :
UnpProtocol(), selfDisconnect(false), timerId(0)
{
}
void UnpClientProtocol::run()
{
fSocket = new QTcpSocket(this);
UnpProtocol::run();
if (timerId)
killTimer(timerId);
}
void UnpClientProtocol::timerEvent(QTimerEvent *event)
{
UnpProtocol::timerEvent(event);
if (event->timerId() == timerId)
{
#ifdef QT_DEBUG
qDebug() << "Reconnect timer event! Trying to reconnect...";
#endif
killTimer(timerId);
timerId = 0;
unpConnect();
}
}
void UnpClientProtocol::unpConnect()
{
selfDisconnect = false;
UnpProtocol::unpConnect();
fSocket->connectToHost(hostAddress, portNumber);
}
void UnpClientProtocol::unpDisconnect()
{
UnpProtocol::unpDisconnect();
selfDisconnect = true;
fSocket->disconnectFromHost();
fSocket->waitForDisconnected();
}
void UnpClientProtocol::onTcpConnected()
{
UnpProtocol::onTcpConnected();
emit needRegistration();
}
void UnpClientProtocol::onTcpDisconnected()
{
UnpProtocol::onTcpDisconnected();
if (!selfDisconnect)
{
m_connected = false;
emit registrationResult(m_connected);
if (timerId)
killTimer(timerId);
#ifdef QT_DEBUG
qDebug() << "Starting reconnect timer";
#endif
timerId = startTimer(5000);
}
}
void UnpClientProtocol::onTcpError(QAbstractSocket::SocketError err)
{
UnpProtocol::onTcpError(err);
emit registrationResult(m_connected);
if (timerId)
killTimer(timerId);
#ifdef QT_DEBUG
qDebug() << "Starting reconnect timer";
#endif
timerId = startTimer(5000);
}
Проблема в том, что при срабатывании слота UnpProtocol::onThreadStop() и вызове внутри метода unpDisconnect() вызывается метод UnpProtocol::unpDisconnect(), а не UnpClientProtocol::unpDisconnect(). Причем, если вызвать unpDisconnect() из метода UnpProtocol::run() (я закомментировал строку), то нормально срабатывает UnpClientProtocol::unpDisconnect().
Подскажите, где ошибся!!!
Скорее всего UnpProtocol::onThreadStop() отрабатывает из деструктора UnpProtocol().
Да, так и было. Остановка процесса выполняется в деструкторе UnpProtocol, а завершение работы производилось просто delete unp. Получается, что при выполнении деструктора контекст потомка уже "потерян" или удален. Изменил немного код и перед удаление экземпляра класса вставил unp->quit(); unp->wait(); delete unp; И все заработало как надо