QTimer in a Singleton QObject class stops emitting timeOut()



  • Hi all,

    I'm having troubles synchronizing network communications from my GUI application. Several QoS routines poll both UDP and TCP network devices on different QHostaddresses.
    To streamline the communication over the network I've created a Signleton class named AcpNetwork which holds a QHash<ulong, AcpTransport *> named fifo.
    @private:
    static AcpNetwork *m_Instance;
    typedef struct
    {
    QHostAddress address;
    int retries;
    TransportState state;
    QWaitCondition *wait;
    AcpPacket *request;
    AcpPacket *reply;
    } AcpTransport;
    QTimer *fifoTimer;
    QHash<ulong, AcpTransport *> fifo;
    private slots:
    void handlePackets();@
    The fifoTimer is started at AcpNetwork initialization and ticks every 100ms. At the timeout() signal, handlePackets() is called.
    @AcpNetwork::AcpNetwork(QObject *parent) : QObject(parent)
    {
    QTimer *timer = new QTimer();
    timer->setInterval(100);
    timer->setSingleShot(false);
    connect(timer, SIGNAL(timeout()), this, SLOT(handlePackets()));
    timer->start();
    }@
    handlePackets iterates of the the QHash and sends the AcpPacket request. After several milliseconds the reply is asynchronous handled and assigned to the QHash AcpPacket reply. And the waiting caller (blocked by the QWaitCondition) is signaled that the reply is available.

    handlePackets() only takes action when there are items in the QHash, so the first seconds of my application, this slot does nothing.
    When the first packet is added to the fifo, the machanism works like a charm. I can see that the packet is written to the socket, Wiresharks detects the packet, sees the reply, my application reads the data from the socket and adds the AcpPacket to the reply pointer. The state is set to received and the calling QObject is woken throught the QWaitCondition.

    After that the whole mechanism comes to a stop with no error or warning thrown. I can see that there are request packages added to the fifo, but the handlePackets() slot is never triggered anymore.

    I've searched the interwebz regarding this issue, but so far none of the answers solve my problem:
    http://www.qtcentre.org/threads/30353-QThread-QWaitCondition-and-freeze
    http://stackoverflow.com/a/13225297
    http://qt-project.org/forums/viewthread/11316
    https://qt-project.org/forums/viewthread/26159

    What can be the issue of this matter?

    Hope to hear from you soon and many thanks in advance!

    TOAOMatis



  • Hi,

    remember that each Thread has its EventLoop; this means that the handlePackets() slot will be triggered only for the QThread who created it.

    Have a look "here":http://qt-project.org/doc/qt-5/threads-qobject.html to more details



  • Here is some info from the docs on QTimer that may apply to your situation and be helpful:

    In multithreaded applications, you can use QTimer in any thread that has an event loop. To start an event loop from a non-GUI thread, use QThread::exec(). Qt uses the timer's thread affinity to determine which thread will emit the timeout() signal. Because of this, you must start and stop the timer in its thread; it is not possible to start a timer from another thread.

    I noticed you use a QWaitCondition. It could be that the event from the timer is fired off before the wait condition is blocking again. If that happens then the wait will have no idea the event fired off (and was handled/ignored) already and block forever.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.