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. SetProperty : Cannot send events to objects owned by a different thread
QtWS25 Last Chance

SetProperty : Cannot send events to objects owned by a different thread

Scheduled Pinned Locked Moved General and Desktop
11 Posts 3 Posters 15.2k Views
  • 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.
  • D Offline
    D Offline
    dvdk
    wrote on last edited by
    #1

    I set some dynamic properties on QObjects from different threads using QObject->setProperty()
    I was under the impression this is executed by posting a QDynamicPropertyChangeEvent so I didn't have to worry about what thread it was sent from.

    This seemed to work on linux, but on windows I get the following assert :

    @ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread.@

    What would be the best approach to set Dynamic properties in a multi threaded application?

    1 Reply Last reply
    0
    • A Offline
      A Offline
      andre
      wrote on last edited by
      #2

      AFAIK, the event is there to enable you to act on the change, but they are not used to make the actual change. An inspection of the sources can tell you the details.

      I guess I'd create a slot on the class as a thin wrapper for setProperty. That would enable you to use the cross-thread signal/slot mechanism (either via a signal or by using QMetaObject) to set the properties.

      1 Reply Last reply
      0
      • D Offline
        D Offline
        dvdk
        wrote on last edited by
        #3

        I suppose you are right about the event. Thanks for clearing that up :)
        Are you suggesting to create a wrapper for every QObject derived class I want to use to set a dynamic property? Since I use a lot of the QWidgets, this seems like an impossible job to maintain.

        Any idea why this behaviour only manifests on windows and not on linux?

        1 Reply Last reply
        0
        • D Offline
          D Offline
          dbzhang800
          wrote on last edited by
          #4

          Hi dvdk,

          Though all functions in class QObject are reentrant, but only connect() and disconnect() are thread-safe. And you should not use not-thread-safe method in this way.

          You can using signals and slots between threads(with auto connection or queued connection), which is easy and safe.

          Regards,

          Debao

          1 Reply Last reply
          0
          • D Offline
            D Offline
            dvdk
            wrote on last edited by
            #5

            I understand I should use cross-thread signaling, but I fail to see how I can achieve this in a simple way.

            Say I want to do a setProperty on a QLabel object, how can I achieve this with signals without writing a wrapper round QLabel (and every other qwidget I like to use)? setProperty is not a slot.

            1 Reply Last reply
            0
            • D Offline
              D Offline
              dbzhang800
              wrote on last edited by
              #6

              You did not say that the QObject you mentioned is QWidget before.

              [quote author="dvdk" date="1333131332"]
              Say I want to do a setProperty on a QLabel object, how can I achieve this with signals without writing a wrapper round QLabel (and every other qwidget I like to use)? setProperty is not a slot.[/quote]

              In fact, You cannot! The manual says:

              bq. Although QObject is reentrant, the GUI classes, notably QWidget and all its subclasses, are not reentrant. They can only be used from the main thread.

              By the way, if you want to call slots or signals or invoked methods, you can use
              @
              QMetaObject::invokeMethod()
              @

              1 Reply Last reply
              0
              • A Offline
                A Offline
                andre
                wrote on last edited by
                #7

                Well, that's an issue, indeed.

                If your issue is to set properties from different threads to your GUI thread (you're talking about widgets, after all), then I think I'd create a QObject derived class, of which you create an instance in your main tread. You can use that class as a proxy to your widget. Simply pass the pointer to the widget, as well as the property name and the QVariant value to that class via the threaded signal/slot mechanism, and let that class then do the actual property setting.

                1 Reply Last reply
                0
                • D Offline
                  D Offline
                  dvdk
                  wrote on last edited by
                  #8

                  Thanks Andre, your solutions looks very clean. I will implement the proxy class.

                  1+1=2 :
                  Just out of curiosity I wanted to try your hint about InvokeMethod(), but I can't figure out how to use it properly.

                  I tried the following

                  @QMetaObject::invokeMethod(pObj, "setProperty", Qt::AutoConnection,
                  Q_ARG(const char*, "somevar"), Q_ARG(const QVariant, "somevalue"));@

                  It compiles fine, but on execution I get :

                  @QMetaObject::invokeMethod: No such method QLabel::setProperty(const char*,const QVariant)@

                  Any idea what I did wrong? Documentation on Q_ARG is a bit thin, I probably misinterpreted something.

                  1 Reply Last reply
                  0
                  • A Offline
                    A Offline
                    andre
                    wrote on last edited by
                    #9

                    What you are doing wrong, is that on QLabel, setProperty is not declared as a a slot, or at least as Q_INVOKABLE. This functionality is basically a 'raw' way of using the signal/slot mechanism, and it relies on the same mechanisms.

                    1 Reply Last reply
                    0
                    • D Offline
                      D Offline
                      dvdk
                      wrote on last edited by
                      #10

                      Thanks for the answer. So the QMetaObject::invokeMethod cannot be used in this case.

                      1 Reply Last reply
                      0
                      • A Offline
                        A Offline
                        andre
                        wrote on last edited by
                        #11

                        well, it can be used through the proxy object that I suggested. You can use QMetaObject::invokeMethod on the slot you define there. That slot can then use a normal method invocation on the object you pass for the actual property setting. The invokeMethod should use the Qt::QueuedConnection connection type.

                        The proxy object could be quite simple, I guess something like this would suffice:

                        @
                        class PropertySetProxy: public QObject
                        {
                        Q_OBJECT

                        public:
                        PropertySetProxy(QObject* parent = 0): QObject(parent) {}

                        setProperty(const QObject* target, const char* property, QVariant value);
                        

                        };

                        //implementation
                        PropertySetProxy::setProperty(const QObject* target, const char* property, QVariant value)
                        {
                        //check if target object lives in the same thread as we do
                        if (thread() != target->thread()) {
                        qWarning() << "Can't set property of object living in different thread!";
                        return;
                        }

                        target->setProperty(property, value);
                        }
                        @

                        Note: brain to forum editor, code is not tested and to be understood as an example only.

                        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