2014-01-13 5 views
0

Я создал нить содержит QTcpServer, который принимает любые входящие соединения:Доступ QTcpSocket из другого потока (дочерний поток)

void Service::run() //Service class is a subclass of QThread 
{ 
    server->listen(QHostAddress::LocalHost, ServicePortNo); 
    // server is a private member of Service  

    while(server->waitForNewConnection(-1)){ 
     QTcpSocket *socket = server->nextPendingConnection(); 
     handle(socket); // This is a pure virtual function 
    } 
} 

в handle(QTcpSocket *socket):

// TimeDateService is subclass of Service 
// implementation of pure virtual function handle() 
void TimeDateService::handle(QTcpSocket *socket) 
{ 
    (new TimeDateSocketHandler(socket))->Start(); 
} 

Примечание: TimeDateSocketHandler является подкласс SocketHandler и SocketHandler сам по себе является подклассом QThread, как показано ниже:

void SocketHandler::run() 
{ 
    if(!socket->waitForReadyRead(WAIT_TIMEOUT)) 
    { 
     socket->disconnectFromHost(); 
     socket->close(); 
     return; 
    } 
    QByteArray request = socket->readAll(); 
    QByteArray response = Serve(request); // Serve is a pure virtual function 
    socket->write(response); 
    socket->waitForBytesWritten(WAIT_TIMEOUT); 
    socket->disconnectFromHost(); 
    socket->close(); 
} 

И, наконец, вот главная функция TimeDateSocketHandler

QByteArray TimeDateSocketHandler::Serve(QByteArray request) 
{ 
    QByteArray response; 
    response.append(QTime::currentTime().toString().toUtf8()); 
    response.append(QString(SEPARATOR).toUtf8()); 
    response.append(QDate::currentDate().toString().toUtf8()); 
    return response; 
} 

:

int main(int argc, char *argv[]) 
{ 
    QCoreApplication a(argc, argv); 

    TimeDateService timedateService; 
    //CalculatorService calculatorService; 
    //RemoteCMDService remoteCMDService; 

    timedateService.StartService(); 
    //calculatorService.StartService(); 
    //remoteCMDService.StartService(); 

    return a.exec(); 
} 

В функции main я начал TimeDateService. Но при подключении к серверу для получения даты и времени, сервер отправляет время и дату, но когда TimeDateSocketHandler хочет закрыть сокет программных сбоев:

ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects ow ned by a different thread. Current thread 3998779bf0. Receiver '' (of type 'QNat iveSocketEngine') was created in thread 39985efcd0", file kernel\qcoreapplicatio n.cpp, line 494

Может кто-нибудь помочь мне, пожалуйста, как я могу решить эту проблему Большое спасибо

+0

Пожалуйста, покажите свою основную функцию (содержащую интуицию и подключение). Кроме того, было бы лучше, если бы вы не подклассы QThread ... – lpapp

+0

@LaszloPapp Спасибо за ваш ответ, я обновил вопрос, пожалуйста, см. Его –

ответ

1

Ваша проблема эта линия:

(new TimeDateSocketHandler(socket))->Start(); 

родитель «гнездо» живет в TimeDateService потоке, но ребенок будет находиться в потоке TimeDateocketHandler. Родитель и дети должны быть в одном потоке при использовании цикла событий Qt.

Вот соответствующая часть documentation:

Event filters are supported in all threads, with the restriction that the monitoring object must live in the same thread as the monitored object. Similarly, QCoreApplication::sendEvent() (unlike postEvent()) can only be used to dispatch events to objects living in the thread from which the function is called. Here is an example of that:

Решение относительно прямолинейно:

  • Вы можете вызвать метод непосредственно с invokeMethod method of QMetaObject. Вам нужно будет использовать очередное соединение, чтобы получить слот, запускаемый в отдельном потоке.

    QMetaObject :: InvokeMethod (новый TimeDateSocketHandler (гнездо), SLOT (Start()), Qt :: QueuedConnection);

или

  • Использование сигналов и слотов. Это означает, что вместо прямого вызова выдается сигнал, а затем подключается соответствующий слот другого потока.

    TimeDateSocketHandler * timeDateSocketHandler = новый TimeDateSocketHandler (сокет);

    connect (это, СИГНАЛ (socketHandled()), timeDateSocketHandler, SLOT (Start()));

    emit socketHandled();

или

  • Используйте смарт-указатель (например QSharedPointer) вместо сырой указатель

  • Перемещение к обработке в другой поток сокета.

+0

спасибо за ваш ответ! но я хочу обрабатывать каждый сокет (входящее соединение) в отдельном потоке, чтобы избежать блокирования сервера. Можете ли вы предложить мне решение этой проблемы? –

+0

Мне жаль дорогой Ласло, я новичок в многопоточности в Qt, вы можете объяснить больше второго решения, пожалуйста, –

+0

@ABFORCE: сделано, но вы должны использовать третье решение. – lpapp

Смежные вопросы