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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Сегментация при удалении сокета в потоке  (Прочитано 5036 раз)
Fregloin
Супер
******
Offline Offline

Сообщений: 1025


Просмотр профиля
« : Сентябрь 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; //закоментируем удаление сокета в деструктрое программы
}
то програ не вылетает, но и не вызывается деструктор сокета. В чем проблема?
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #1 : Сентябрь 22, 2011, 10:22 »

Лень читать код, но думаю, deleteLater тебе поможет.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Fregloin
Супер
******
Offline Offline

Сообщений: 1025


Просмотр профиля
« Ответ #2 : Сентябрь 22, 2011, 10:33 »

deleteLater применять к сокету или потоку?
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #3 : Сентябрь 22, 2011, 10:36 »

К сокету. delete  fcanSocket -> fcanSocket->deleteLater ()
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Fregloin
Супер
******
Offline Offline

Сообщений: 1025


Просмотр профиля
« Ответ #4 : Сентябрь 22, 2011, 10:37 »

так и сделал, теперь при вызове disconnectFormServer получаю
QThread: Destroyed while thread is still running
Записан
andrew.k
Гость
« Ответ #5 : Сентябрь 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.
Записан
Fregloin
Супер
******
Offline Offline

Сообщений: 1025


Просмотр профиля
« Ответ #6 : Сентябрь 22, 2011, 16:19 »

а как мне тогда обращаться к сокету из других потоков?
Записан
andrew.k
Гость
« Ответ #7 : Сентябрь 26, 2011, 11:44 »

а как мне тогда обращаться к сокету из других потоков?
А в чем проблема?
Записан
andrew.k
Гость
« Ответ #8 : Сентябрь 26, 2011, 11:45 »

Я ни в коем случае не говорю, что коннекты надо убрать. Их нужно переместить в run и там же создавать экземпляр QSocket.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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