5

Besides QMetaObject::invokeMethod is there any type-safe way of invoking a method/slot asynchronously (a.k.a queuing its execution in the GUI thread)?

The QMetaObject::invokeMethod doesn't have compile-time checking for function names. There is also an overhead in specifying the member function by a string since a lookup and string matching is performed for every call.

I wonder if there is anything similar to the new QObject::connect syntax for invoking a method that provides compile time checking.

One solution is using the signal-slot architecture, but this enforces wrapping each caller code in a QObject class to be able to emit that signal.

Isaac
  • 2,332
  • 6
  • 33
  • 59
  • It's basically https://bugreports.qt.io/browse/QTBUG-36861 , I think. – peppe Aug 14 '16 at 16:42
  • @peppe: It seems there is no alternative: https://bugreports.qt.io/browse/QTBUG-55304 – Isaac Aug 14 '16 at 17:21
  • Take a look at [this](https://stackoverflow.com/a/21653558/2666212). So, instead of `QMetaObject::invokeMethod(object, "method")`, you can do something like this: `{QObject src; QObject::connect(&src, &QObject::destroyed, object, &Object::method);}` you can even use a lamba function with a context `QObject` that way. . . – Mike Aug 14 '16 at 17:34
  • @Mike: Nice trick! While this provides the compile-time checking I wonder how much overhead it has compared to string lookup. – Isaac Aug 14 '16 at 17:43
  • Your snippet is a sample that doesn't support passing arguments, but the solution proposed in your link (`postToThread` template function) also supports passing arguments, right? – Isaac Aug 14 '16 at 17:44
  • @Isaac , you can use a lambda function and capture and pass whatever arguments you want from there. – Mike Aug 15 '16 at 00:22
  • @Mike: Ah I see. That is the solution. I am currently tempted about singleShot as it seems to have lower overhead. – Isaac Aug 15 '16 at 00:26
  • @Mike: I guess you can compose an answer from our scattered discussions here and on the other questions. – Isaac Aug 15 '16 at 00:30
  • @Isaac , are you talking about the overhead of creating the signalSource temp `QObject`? – Mike Aug 15 '16 at 00:31
  • @Mike: Yeah. Isn't QTimer::singleShot cheaper? I took a look at source code of QObject constructor and it seemed to be not cheap. I haven't performed any benchmarks though. – Isaac Aug 15 '16 at 00:32
  • Please take a look at `singleShot`'s [implementation](https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/kernel/qtimer.cpp#n390), you can see that it creates a new [`QSingleShotTimer`](https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/kernel/qtimer.cpp#n258)(which inherits `QObject`) and then its constructor calls [`QObject::startTimer`](https://doc.qt.io/qt-5/qobject.html#startTimer). After reading this I can say that the temporary singnalSource `QObject` is cheaper than using a timer where you don't need to at least. . . – Mike Aug 15 '16 at 00:42
  • @Mike: Oh... I see. Well I guess I stick to the `postToThread` solution untiil. I doubt if it is more expensive than invokeMethod, and its compile-time checking is really important for me. Thanks Mike. – Isaac Aug 15 '16 at 00:53

2 Answers2

1

It is possible to use the QTimer::singleShot for this purpose

QTimer::singleShot(0, object, &Object::method...);
--
QTimer::singleShot(0, object, [object](){
  object->method(arg1, arg2, ...);
});

Note: The thread in which QTimer::singleShot is invoked must have an QEventLoop.

thomas
  • 330
  • 3
  • 10
  • Yeah. I've seen this solution in the link provided by Mike. Do you have any comments on the overhead of this solution compared to other methods? – Isaac Aug 14 '16 at 19:14
0

Please see this https://doc.qt.io/qt-5/qmetaobject.html#invokeMethod-4

template <typename Functor, typename FunctorReturnType> bool QMetaObject::invokeMethod(QObject *context, Functor function, FunctorReturnType *ret)

This is an overloaded function.

Invokes the function in the event loop of context using the connection type Qt::AutoConnection. function can be a functor or a pointer to a member function. Returns true if the function could be invoked. Returns false if there is no such member or the parameters did not match. The return value of the function call is placed in ret.

Note: This function is thread-safe.

This function was introduced in Qt 5.10.

Roman Ivasyshyn
  • 118
  • 1
  • 8