Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. [SOLVED] QTest and QObject::killTimer warning
Forum Updated to NodeBB v4.3 + New Features

[SOLVED] QTest and QObject::killTimer warning

Scheduled Pinned Locked Moved General and Desktop
5 Posts 2 Posters 6.1k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    milgner
    wrote on last edited by
    #1

    I'm still quite new to the Qt framework and I have a question regarding QTest, timers and threads, which despite there being a few posts about already I still find myself unable to answer:

    Some of my code requires the use of Windows asynchronous I/O and to not get in conflict with the Qt event loop, I decided to create my own thread using native _beginthreadex. From there I dispatch signals to the QObject using QMetaObject::invokeMethod and specifying Qt::QueuedConnection as is also described in http://qt-project.org/forums/viewthread/13817
    At first this was working great, when the object receiving these signals was on the Qt main thread but now I created a separate QThread object (no subclassing) and suddenly I receive these dreaded QObject::killTimer warnings "timers cannot be stopped from a different thread".
    The forum posts I found almost always have something to do with subclassing QThread (which I didn't do) and also using timers - which I'm also not using, at least not explicitly. My guess is that something in QTest does.
    Since it's a unit test, the participating classes are quite few: my class under test, QSignalSpy and QThread.
    Effectively, I suspect either QSignalSpy::wait or QTRY_COMPARE_WITH_TIMEOUT to issue these messages. Yet moving the spy to the other thread doesn't seem to have any effect.

    If anyone has an idea, it would be greatly appreciated!

    1 Reply Last reply
    0
    • JKSHJ Offline
      JKSHJ Offline
      JKSH
      Moderators
      wrote on last edited by
      #2

      Sounds like something is being executed in the wrong thread. Can you post the code of your class under test?

      Since I haven't seen your code, I can only give general hints:

      By default, a QObject lives in the thread that created it

      When a QObject is moved to another thread, its child QObjects are moved too

      A QObject's member variables do not automatically become its children -- the parent-child relationship needs to be set explicitly, either using the constructor or setParent()

      From #1, if an object has QObjects as member variables, those member QObjects live in the thread that created them

      From #3, if a QObject has non-child member variables, and the owning QObject is moved to another thread, those member variables are not moved with the owning object

      All QObjects have a built-in timer, accessible by QObject::startTimer() and QObject::killTimer

      Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

      1 Reply Last reply
      0
      • M Offline
        M Offline
        milgner
        wrote on last edited by
        #3

        Thank you for the quick reply! Indeed it did clear up some blank spots in my understanding of Qt and threading.
        Unfortunately the class tested is quite complex so I can't publish it in full here. I'll do some lobbying to make the component OSS once it works, though.
        It's an improved version of the QFileSystemWatcher, which, as also written by one of the devs http://blog.rburchell.com/2012/03/qt-51-aka-when-qfilesystemwatcher-might.html is lacking in some features at the moment.
        My class uses Win32 ReadDirectoryChangesW asynchronous I/O to monitor directories and emits more specialized signals for created, modified and deleted files.
        As a general overview of the architecture, it's like this:

        QImprovedFileSystemWatcher : public QObject

        • has QString and QList members, which don't seem to have moveToThread
        • holds DirectoryMonitor, not derived from QObject
          • DM evokes signals on owning class using QMetaObject::invokeMethod

        TestClass : QObject

        • instantiated on main thread
        • uses QSignalSpy
        • works fine, but complains about kill timer when putting file system watcher on a separate thread

        A sample test method, which sometimes gives the warning, sometimes it doesn't:

        @void
        QImprovedFileSystemWatcherTest::testSingleCreate() {
        QSignalSpy createFileSpy(m_watcher, SIGNAL(fileCreated(const QFileInfo&)));
        m_watcher->startWatching();

        auto filePath = m_tempDir->path()+"\testFile.txt";
        QFile createdFile(filePath);
        QVERIFY2(createdFile.open(QIODevice::WriteOnly), QString("Could not create test file %1").arg(filePath).toUtf8());
        createdFile.close();

        QTRY_COMPARE_WITH_TIMEOUT(createFileSpy.count(), 1, 2000);
        QFileInfo argument = createFileSpy.takeFirst().takeFirst().value<QFileInfo>();
        QCOMPARE(argument.fileName().toUtf8().constData(), "testFile.txt");
        }
        @

        1 Reply Last reply
        0
        • M Offline
          M Offline
          milgner
          wrote on last edited by
          #4

          Update: I found a kind of solution to this by removing the separate thread from my test class. Signals are correctly dispatched from the Windows-managed thread to Qt.
          But now that I'm using QTRY_COMPARE_WITH_TIMEOUT in my test, it will switch back into the Qt event loop and allow it to process the messages which have been queued for the object which resides in the same thread, letting the signal-spying succeed.

          So I still suspect there is something fishy with using this macro in conjunction with an object that resides on another thread but I can look into that in my free time.

          Thank you again for your helpful insight into the event loop, JKSH!

          1 Reply Last reply
          0
          • JKSHJ Offline
            JKSHJ Offline
            JKSH
            Moderators
            wrote on last edited by
            #5

            You're welcome :) Thank you for providing details even if you can't post the code -- it certainly makes it easier for others to understand your issue properly!

            [quote author="Marcus Ilgner" date="1373373765"]

            • has QString and QList members, which don't seem to have moveToThread
              [/quote]The concept of "thread affinity":http://qt-project.org/doc/qt-5.1/qtcore/threads-qobject.html only applies to QObjects. In C++, data is equally accessible to all threads -- Non-QObjects don't inherently "belong" to a particular thread, so you can't "move" them between threads.

            [quote]TestClass : QObject

            • instantiated on main thread
            • works fine, but complains about kill timer when putting file system watcher on a separate thread[/quote]This could be a source of your problem.

            Just because a QObject lives in a particular thread doesn't mean that all its methods will automatically run in that thread. Queued slots will run in the thread that the QObject lives in, only if the slot is invoked with a signal/event or QMetaObject::invokeMethod(). But, if anything from your main thread directly calls any of the watcher's member functions (including slots), then those functions will run in the main thread.

            Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved