4

I want to call object's slot in its own thread. In other word, to put slot processing into receiver's thread queue.

As I know, it could be done by using

QMetaObject::invokeMethod(objPtr, "someMethod", Qt:: QueuedConnection);

But as for me, this way is unsafe. Because there are no any compile-time checks about existence of method with such name. And in case of some mistype, error will occur only in runtime and only in logs.

Another way is to create dummy signal like

void callObj();

and connect this dummy signal to slot

connect(this, &Obj1::callObj, objPtr, &Obj2::someMethod, Qt:: QueuedConnection);

But this way is looks really bad.

So is there any way to do this?

Thanks in advance for help.

Esperan
  • 51
  • 4
  • @H.G - the slot is looked up from a string during runtime, so there is no compile time check. – dtech Oct 07 '16 at 18:06
  • There are some tricks for compile time slot checking in http://stackoverflow.com/questions/26422154/my-signal-slot-connection-does-not-work#26422155 – Martin Beckett Oct 07 '16 at 18:10
  • I think that the tricks in [this answer](https://stackoverflow.com/a/21653558/2666212) can be useful here. Anyway, there is a [QTBUG](https://bugreports.qt.io/browse/QTBUG-55304) about it. – Mike Oct 07 '16 at 18:40

2 Answers2

4

If you have definition of the interface you'll be calling against, you can use a single shot QTimer with 0ms timeout:

QTimer::singleShot(0, obj, &Class::slot);

you can also call it with a lambda

QTimer::singleShot(0, obj, [obj]{ obj->slot(42); } );

This approach requires the target thread to run its own event loop (i.e. QThread::exec()), but since you want to run slots in its thread I assume that's what you want.

krzaq
  • 16,240
  • 4
  • 46
  • 61
  • 1
    Well, that's how I've shown it in the example. I checked the Qt sources before posting this answer and it does the right thing - calls `moveToThread(r->thread())` in QTimer constructor. [link](https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qtimer.cpp.html#_ZN16QSingleShotTimerC1EiN2Qt9TimerTypeEPK7QObjectPN9QtPrivate15QSlotObjectBaseE) – krzaq Oct 07 '16 at 18:22
0

It is not unsafe - nothing bad will happen, invokeMethod() will return false if the method doesn't exist. Check the return value to decide further course of action. It won't crash or anything like that.

You can use qobject_cast to make sure your pointer is of the right type, which should be enough to verify if it has the particular method. Other than that, take care not to mistype it and don't use untested code.

Also, consider that there are several other ways to leverage multithreading besides the implicit object thread affinity.

I wouldn't call the dummy signal approach "really bad" - it is just a hack, and hacks go hand in hand with Qt, as huge as the framework might be, it is far from fullproof.

dtech
  • 47,916
  • 17
  • 112
  • 190