Results 1 to 6 of 6

Thread: Calling setPlainText() for an object of a different thread leads to assertion failure

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Feb 2006
    Posts
    32
    Thanks
    3
    Thanked 1 Time in 1 Post
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Question Calling setPlainText() for an object of a different thread leads to assertion failure

    Hello,

    I have the following code that is located in the run() method of my class which is derived from QThread:
    Qt Code:
    1. _pEventNotifyDlg->_pDateDisplay->setText("Test1");
    2. _pEventNotifyDlg->_pMessageDisplay->setPlainText("Test2");
    To copy to clipboard, switch view to plain text mode 
    While the first call works fine, the second causes a crash with the following error message:
    Qt Code:
    1. QObject::startTimer: timers cannot be started from another thread
    2. QObject::connect: Cannot queue arguments of type 'QRectF'
    3. ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 81d1800.
    4. Receiver '' (of type 'QTextDocument') was created in thread 8061188", file kernel/qcoreapplication.cpp, line 293
    5. Aborted
    To copy to clipboard, switch view to plain text mode 
    The _pEventNotifyDlg is an instance of a dialog class which belongs to the main thread. _pDateDisplay is a QLabel, and _pMessageDisplay is a QTextBrowser. I do not see that I am sending any events there, but I guess it is triggered by the setPlainText() method call.

    Can anybody explain that behaviour to me? Am I misunderstanding something fundamental about threads?

    Thanks Ben

    QT Version 4.1.3

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,017 Times in 4,793 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Calling setPlainText() for an object of a different thread leads to assertion failure

    Quote Originally Posted by bmesing
    Can anybody explain that behaviour to me? Am I misunderstanding something fundamental about threads?
    I think the message you got is clear.

    Cannot send events to objects owned by a different thread
    You can't operate on objects which live in a different thread. You should use postEvent and handle a custom event which will change contents of the widget.

    The assertion is because it would be dangerous to modify internal data of another thread (or specifically of an object owned by it). Most of methods which operate on widgets are not thread-safe.

    You can read more in the docs -- section about threads. You can also search this forum, there were issues like this (concerning creating objects with parents living in a different thread).

  3. #3
    Join Date
    Feb 2006
    Posts
    32
    Thanks
    3
    Thanked 1 Time in 1 Post
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: Calling setPlainText() for an object of a different thread leads to assertion failure

    Thanks, I've solved my problem by avoiding to use threads.
    However it seems quiet a limitation not being able to access widgets directly. It also seems like one has to know many internals, to distinguish which method call raises an event. Probably its best to avoid calls of any QWidget methods from another Thread.

    Best regards

    Ben

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,017 Times in 4,793 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Calling setPlainText() for an object of a different thread leads to assertion failure

    Quote Originally Posted by bmesing
    However it seems quiet a limitation not being able to access widgets directly.
    If all widget access was to be thread-safe, you'd have to protect every call that changes internal structures of the widget with a mutex, which would cause a great performance hit.

    It also seems like one has to know many internals, to distinguish which method call raises an event.
    No, you don't. As you see Qt cares about it for you. And the general rule is not to do any calls to objects living in another thread without being sure they are thread safe (there is a list of thread safe calls in the docs somewhere).

    Probably its best to avoid calls of any QWidget methods from another Thread.
    Exactly. Most of the calls can be done using signals and slots which are thread-safe in Qt4 and that's how most actions should be handled.In your case it should roughly look like:

    Qt Code:
    1. _pEventNotifyDlg->_pMessageDisplay->setPlainText("Test2");
    2. connect(this,
    3. SIGNAL(someSignal(const QString &)),
    4. _pEventNotifyDlg->_pMessageDisplay,
    5. SLOT(setPlainText(const QString &))
    6. );
    7. //...
    8.  
    9. emit someSignal("some text");
    To copy to clipboard, switch view to plain text mode 

  5. #5
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    6,264
    Thanks
    36
    Thanked 1,519 Times in 1,389 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: Calling setPlainText() for an object of a different thread leads to assertion fai

    Quote Originally Posted by bmesing
    However it seems quiet a limitation not being able to access widgets directly. It also seems like one has to know many internals, to distinguish which method call raises an event. Probably its best to avoid calls of any QWidget methods from another Thread.
    Yes, QWidget and all its subclasses are not reentrant. They can only be used from the main thread.

    You could use signals and slots and a queued connection to pass a QString from "another" thread to the main thread, and just set the text in the main thread..
    J-P Nurmi

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,017 Times in 4,793 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Calling setPlainText() for an object of a different thread leads to assertion fai

    Quote Originally Posted by jpn
    Yes, QWidget and all its subclasses are not reentrant.
    I think they are reentrant (at least most of them), just not thread-safe.

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
  •  
Qt is a trademark of The Qt Company.