Qt 4.7向特定线程发送信号

Qt 4.7向特定线程发送信号,qt,Qt,我有几个客户端GUI窗口,它们都是从QMainWindow派生的。每个窗口可能执行不同的任务,但所有窗口都从作为QThread实现的中央缓存请求数据 所有客户端连接到数据缓存中相同的插槽,然后发出信号s以提示数据缓存执行某些操作。数据缓存的信号将排队,因此数据缓存一次只做一件事 当数据缓存完成时,它需要通知正确的客户端它正在做的事情已经完成。我的直接想法是向请求客户端发出一个关于完成的信号。这意味着连接到特定客户机的插槽,然后向其发出信号 我必须先连接然后断开与客户端的连接吗?我知道使用QObj

我有几个客户端GUI窗口,它们都是从
QMainWindow
派生的。每个窗口可能执行不同的任务,但所有窗口都从作为
QThread
实现的中央缓存请求数据

所有客户端连接到数据缓存中相同的
插槽
,然后发出
信号
s以提示数据缓存执行某些操作。数据缓存的
信号将排队,因此数据缓存一次只做一件事

当数据缓存完成时,它需要通知正确的客户端它正在做的事情已经完成。我的直接想法是向请求客户端发出一个关于完成的
信号。这意味着连接到特定客户机的
插槽
,然后向其发出
信号


我必须先连接然后断开与客户端的连接吗?我知道使用
QObject::sender()
函数获取供应商。是否有某种方式只向发送方(客户端)发送信号?或者有其他方法可以解决这个问题吗?

可能有更简单的方法可以解决您的问题。例如,我会考虑研究这个框架。或者,您也可以重新设计您的设计,以便客户机在请求缓存执行任何操作之前首先连接到缓存上的“完成”信号。如果所有这些都失败了,你也可以考虑依赖这个函数(你的客户机或者你的缓存)。此函数允许您使用任意泛型参数(以线程安全的方式)对任意QObject调用任意方法(前提是您有指向它的指针)

如果您使用
QMetaObject::invokeMethod
方法,那么您应该注意一些缺点。首先,必须使用该方法的字符串名调用该方法,这意味着您在编译时不会发现是否使用了错误的名称。其次,由于您的客户机与中央缓存具有不同的线程亲缘关系,因此当缓存调用其上的方法时,客户机有可能已被销毁(尽管在您的情况下,这对您来说可能不是问题)。最后,您可能不希望缓存知道它必须在其客户机上执行的方法的名称

我没有办法绕过第一个缺点(我不确定在即将发布的Qt5.0版本中是否会有不同的处理方法)。至于第二个和第三个问题,我建议创建一个对象来封装对方法的引用,如下所示:

class MethodReference
{
   MethodReference(QObject* object, const QString& methodName);

   ...

   bool invoke(QGenericArgument val0 = QGenericArgument(),
               QGenericArgument val1 = QGenericArgument(),
               ...
               QGenericArgument val9 = QGenericArgument());

private:
   QPointer<QObject> mObject;
   QString mMethod;
};
class方法参考
{
MethodReference(QObject*对象、常量QString和methodName);
...
bool invoke(QGenericArgument val0=QGenericArgument(),
QGenericArgument val1=QGenericArgument(),
...
qgenericalargument val9=qgenericalargument());
私人:
QPointer-mObject;
QString方法;
};
然后将该对象从客户端传递到缓存。然后缓存对该对象调用invoke

注意使用
QPointer
——这为您提供了一种线程安全的方法,在您尝试调用对象上的方法之前检查对象是否已被销毁。因为我以前做过这件事,所以我还要告诉您,4.8之前的Qt版本有一个错误,它会在多线程上下文中导致崩溃。如果要执行此操作,请使用较新版本的Qt


我希望这是清楚的。

-您在哪里调用
QObject::connect
,以便在客户端和数据缓存之间形成链接-从客户端对象还是从数据缓存这个问题的标题是什么意思?你的应用程序正在创建哪些特定线程客户端对象在收到“数据缓存完成”信号时需要做什么,我的意思是客户端需要从缓存中检索多少数据?澄清@sjwarner注释。我从客户机对象(即QMainwindow派生的对象)调用QObject::connect。我一直假设其中每一个都代表一个单独的GUI线程。返回的数据量取决于,可以是小数据量,也可以是大数据量,具体取决于数据缓存被要求执行的操作。我正在使用指向数据缓存的指针来访问这些数据。被访问的数据在初始化后是静态的,因此没有锁定机制。到目前为止,我没有任何冲突。谢谢@RA。我不得不承认,到目前为止,元对象子系统对我来说有点神秘。到目前为止,我尽可能少地使用它,但看到了你的答案,促使我再次更仔细地研究它。QMetaObject::invokeMethod让我想到了Java,这真的非常有趣