Results 1 to 3 of 3

Thread: UdpSockets, QTimer and QThread errors going from Qt4.8 to Qt5

  1. #1
    Join Date
    Jun 2011
    Posts
    23
    Thanks
    2
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default UdpSockets, QTimer and QThread errors going from Qt4.8 to Qt5

    Hello,

    I have a console application that talks to another (main) application using udp sockets and waits for a reply. I wrote the initial code (which didn't have these problems) in Qt4.8 but I am now on Qt5.5 and it is not working as it was.
    I am getting 3 errors:
    1. "QObject::killTimer: Timers cannot be stopped from another thread" and QObject::startTimer: Timers cannot be stopped from another thread"
    2. QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread
    (this can be 'corrected' by the line : udpReceiverThread->moveToThread(udpReceiverThread); not sure if it is the right thing to do though based on what i have read
    3. replyNotReceived SLOT is not being called (replyTimer).


    main.cpp starts ArcConsoleInput and ArcConsoleInput starts the UdpThread. There are 2 timers in the code

    1. timeoutTimer - if the user has not typed in any commands in 1 minute the ArcConsoleApp quits
    2. replyTimer - the thread waits 5 seconds for a reply, if no reply received (e.g. main app not running) then message goes to std::cout.

    How do I get rid of error #1 and get the replyNotReceived SLOT to run..

    I have being trying for a few days to get this working using various qt websites, pages, forums but not having any luck.

    Thank you for your help


    ArcConsoleInput.h

    Qt Code:
    1. private:
    2. /*! Timer for when there has been no user interaction for userTimeout seconds */
    3. QTimer* timeoutTimer;
    4.  
    5. /*! A SocketNotifier to read from Standard Input */
    6. QSocketNotifier* notifier;
    7.  
    8. /*! A file to read standard input from */
    9. QFile* stdin;
    10.  
    11. /*! A UdpThread that will receive replies from the ARC */
    12. UdpThread* udpReceiverThread;
    13.  
    14. /*! A UDP socket to send requests to the ARC software */
    15. QUdpSocket *udpSocketArcSender;
    To copy to clipboard, switch view to plain text mode 

    ArcConsoleInput.cpp
    Qt Code:
    1. void ArcConsoleInput::networkSetup()
    2. {
    3. //create a sender UDP socket
    4. udpSocketArcSender = new QUdpSocket(this);
    5.  
    6. //create a thread for the a udp receiver sockets
    7. udpReceiverThread = new UdpThread();
    8. udpReceiverThread->start();
    9. //to stop error:QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread
    10. udpReceiverThread->moveToThread(udpReceiverThread);
    11.  
    12. //Create a SocketNotifier to read from Standard Input
    13. stdin = new QFile();
    14. stdin->open(0, QIODevice::ReadOnly);
    15. notifier = new QSocketNotifier(0, QSocketNotifier::Read);
    16. connect(notifier, SIGNAL(activated(int)), this, SLOT(readUserLine()));
    17.  
    18. //Create a timer for when there has been no user interaction for userTimeout seconds
    19. timeoutTimer = new QTimer(0);
    20. connect(timeoutTimer, SIGNAL(timeout()), this, SLOT(timeExpired()));
    21. timeoutTimer->setInterval(userTimeout);
    22. timeoutTimer->start();
    23. }
    24.  
    25. /*****************************************************************
    26.  * Name: sendUserInput
    27.  * Description: Send the line from stdin to the socket for sending to ARC
    28.  ******************************************************************/
    29. void ArcConsoleInput::sendUserInput(QString line)
    30. {
    31. QByteArray datagram = line.toUtf8();
    32. udpSocketArcSender->writeDatagram(datagram.data(), datagram.size(), QHostAddress::LocalHost, quint16(port));
    33. }
    34.  
    35. /*****************************************************************
    36.  * Name: readLine
    37.  * Description: Read the line from stdin and process
    38.  ******************************************************************/
    39. void ArcConsoleInput::readUserLine()
    40. {
    41. QString line;
    42. char buf[1024];
    43. QRegExp rx("[a-z]*[0-9]{1,2}$");
    44.  
    45. stdin->readLine(buf, sizeof(buf));
    46. line = QString::fromStdString(buf).trimmed().toLower();
    47.  
    48. if(line != NULL)
    49. {
    50. std::cout << "\n" << std::flush;
    51.  
    52. if((QString::compare(line, "quit", Qt::CaseInsensitive) == 0) ||
    53. (QString::compare(line, "exit", Qt::CaseInsensitive) == 0))
    54. {
    55. qDebug("Exiting Console Application");
    56. exit(1);
    57. }
    58. else if (QString::compare(line, "status", Qt::CaseInsensitive) == 0)
    59. {
    60. udpReceiverThread->setReplyReceived(false);
    61. sendUserInput(line);
    62. }
    63. //more stuff here
    64. else
    65. {
    66. qDebug() << "Unknown console input! " << line << "\nType help for assistance";
    67. std::cout << "\n>" << std::flush;
    68. }
    69.  
    70. restartTimer();
    71.  
    72. }
    73. else //empty line - user interaction has occurred
    74. {
    75. std::cout << ">" << std::flush;
    76. restartTimer();
    77. }
    78. }
    79.  
    80. /*****************************************************************
    81.  * Name: restartTimer
    82.  * Description: User interaction has occurred restart the timer
    83.  ******************************************************************/
    84. void ArcConsoleInput::restartTimer()
    85. {
    86. if(timeoutTimer->isActive() == true)
    87. timeoutTimer->stop();
    88.  
    89. if(timeoutTimer->isActive() == false)
    90. timeoutTimer->start();
    91. }
    92.  
    93. /*****************************************************************
    94.  * Name: timeExpired
    95.  * Description: ArcConsoleApp will automatically close if no user interaction for "userTimeout" seconds
    96.  ******************************************************************/
    97. void ArcConsoleInput::timeExpired()
    98. {
    99. qDebug("\nTimeout: ArcConsoleApp is closing!");
    100. delete udpSocketArcSender;
    101. }
    To copy to clipboard, switch view to plain text mode 


    UdpThread.h
    Qt Code:
    1. class UdpThread : public QThread
    2. {
    3. Q_OBJECT
    4.  
    5. public:
    6.  
    7. /*! Constructor */
    8. UdpThread();
    9.  
    10. /*! Destructor */
    11. ~UdpThread();
    12.  
    13. /*! Wait for pending datagrams from the socket to read */
    14. void run() override;
    15.  
    16. /*! set the value of the reply */
    17. void setReplyReceived(bool r);
    18.  
    19. /*! get the value of replyReceived */
    20. bool getReplyReceived();
    21.  
    22. private slots:
    23.  
    24. /*! Read all pending datagrams from the socket and print to screen */
    25. void readPendingDatagrams();
    26.  
    27. /*! Slot for when a reply from ARC has not been received for replyTimeout */
    28. void replyNotReceived();
    29.  
    30. private:
    31. /*! 5 second timer for the receipt of a reply from ARC */
    32. QTimer *replyTimer;
    33.  
    34. /*! UDP Socket to receive replies from the ARC */
    35. QUdpSocket *udpSocketReceiver;
    36.  
    37. /*! Has a reply been received */
    38. bool replyReceived;
    39.  
    40. Q_Log *logging;
    41. };
    To copy to clipboard, switch view to plain text mode 


    UdpThread.cpp
    Qt Code:
    1. #include <signal.h>
    2. #include <iostream>
    3. #include <QtNetwork>
    4. #include <QString>
    5.  
    6. #include "UdpThread.h"
    7.  
    8. static const int replyTimeout = 1 * 5000; //5 seconds
    9. #define RECEIVING_PORT 34568
    10.  
    11. /*****************************************************************
    12. * Name: UdpThread
    13. * Description: Constructor.
    14. ******************************************************************/
    15. UdpThread::UdpThread() : replyTimer(), udpSocketReceiver(), replyReceived(false), logging()
    16. {
    17. udpSocketReceiver = new QUdpSocket(this);
    18. udpSocketReceiver->bind(QHostAddress::LocalHost, RECEIVING_PORT);
    19.  
    20.  
    21. replyTimer = new QTimer(0);
    22. connect(replyTimer, SIGNAL(timeout()), this, SLOT(replyNotReceived()));
    23. replyTimer->setInterval(replyTimeout);
    24. }
    25.  
    26. /*****************************************************************
    27. * Name: ~UdpThread
    28. * Description: Destructor
    29. ******************************************************************/
    30. UdpThread::~UdpThread()
    31. {
    32. delete udpSocketReceiver;
    33. setTerminationEnabled(true);
    34. qDebug("Closing UDP Receiver Thread in ARC Console App");
    35. }
    36.  
    37. /*****************************************************************
    38. * Name: run
    39. * Description: Wait for pending datagrams from the socket to read
    40. ******************************************************************/
    41. [[noreturn]] void UdpThread::run(void)
    42. {
    43. QString msg;
    44.  
    45. for(;;)
    46. {
    47. if(udpSocketReceiver->hasPendingDatagrams())
    48. {
    49. readPendingDatagrams();
    50. }
    51. }
    52. }
    53.  
    54. /*****************************************************************
    55. * Name: readPendingDatagrams
    56. * Description: Read all pending datagrams from the socket and print to screen
    57. ******************************************************************/
    58. void UdpThread::readPendingDatagrams()
    59. {
    60. QString msg;
    61.  
    62. while (udpSocketReceiver->hasPendingDatagrams())
    63. {
    64. QByteArray datagram;
    65. datagram.resize(static_cast<int>(udpSocketReceiver->pendingDatagramSize()));
    66. QHostAddress senderAddr = QHostAddress::LocalHost;
    67. quint16 senderPort = RECEIVING_PORT;
    68.  
    69. udpSocketReceiver->readDatagram(datagram.data(), datagram.size(),
    70. &senderAddr, &senderPort);
    71.  
    72. //qDebug("%s", datagram.data());
    73. qDebug() << datagram.data();
    74. msleep(50); //to get all datagrams in the same request together without exiting while loop
    75.  
    76. if(replyTimer->isActive() == true)
    77. replyTimer->stop();
    78.  
    79. setReplyReceived(true);
    80. }
    81. std::cout << "\n>" << std::flush;
    82. }
    83. /*****************************************************************
    84. * Name: setReplyReceived
    85. * Description: set the value of the reply
    86. ******************************************************************/
    87. void UdpThread::setReplyReceived(bool r)
    88. {
    89. replyReceived = r;
    90.  
    91. if(r == false) {
    92. replyTimer->start();
    93. }
    94. }
    95.  
    96. /*****************************************************************
    97. * Name: getReplyReceived
    98. * Description: get the value of replyReceived
    99. ******************************************************************/
    100. bool UdpThread::getReplyReceived(void)
    101. {
    102. return replyReceived;
    103. }
    104.  
    105. /*****************************************************************
    106. * Name: replyNotReceived
    107. * Description: Slot for when a reply from ARC has not been received for replyTimeout
    108. ******************************************************************/
    109. void UdpThread::replyNotReceived()
    110. {
    111. std::cout << "No reply received, try again or check that ARC is running!\n\n>" << std::flush;
    112.  
    113. if(replyTimer->isActive() == true)
    114. replyTimer->stop();
    115. }
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Jun 2011
    Posts
    23
    Thanks
    2
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: UdpSockets, QTimer and QThread errors going from Qt4.8 to Qt5

    If i change the line:
    udpReceiverThread->moveToThread(udpReceiverThread);
    to
    udpReceiverThread->moveToThread(this->thread());

    the replyNotReceived() works correctly. but i get both these errors:
    QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread
    QObject::killTimer: Timers cannot be stopped from another thread

    The QSocketNotifier error only happens once but the but the killTimer error happens every time there is a reply. Where there is no reply because the other application that is to response is not running, I get neither error.

    Not sure if this helps?

  3. #3

    Default Re: UdpSockets, QTimer and QThread errors going from Qt4.8 to Qt5

    Considering the transition from Qt4.8 to Qt5, it seems the issues are related to threading complexities, specifically with QSocketNotifier and killTimer. Have you considered other approaches or modifications to the threading mechanism that might resolve these errors while maintaining the correct functionality of replyNotReceived() in your application?

Similar Threads

  1. QThread and QTimer
    By bibhukalyana in forum Qt Programming
    Replies: 6
    Last Post: 23rd September 2013, 15:59
  2. When should i use QThread and QTimer
    By NathiyaAmose in forum Qt Programming
    Replies: 4
    Last Post: 5th August 2013, 12:02
  3. Replies: 15
    Last Post: 4th August 2012, 20:11
  4. QThread and QTimer
    By sivrisinek in forum Qt Programming
    Replies: 4
    Last Post: 30th April 2009, 17:41
  5. QTimer and QThread
    By TheKedge in forum Qt Programming
    Replies: 4
    Last Post: 21st September 2006, 15:52

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.