我有几个客户端图形用户界面窗口,它们都是从QMainWindow派生的。每个窗口都可能执行不同的任务,但都从实现为QThread的中央缓存请求数据。
所有客户端都连接到数据缓存中的同一个slot,然后发出signal以提示数据缓存执行某些操作。数据高速缓存的signal会排队,因此数据高速缓存一次只做一件事。
当数据缓存完成时,它需要通知正确的客户端它正在做的事情已经完成。我的第一个想法是向发出请求的客户端发出一个关于完成的signal。这将意味着连接到特定客户端的slot,然后向其发出signal。
我必须先连接然后再断开与客户端的连接吗?我知道用于获取供应商的QObject::sender()函数。有没有什么方法可以只向发送者(客户端)发送信号?还是有其他方法可以做到这一点?
发布于 2012-08-18 06:02:37
也许你可以采用更简单的方法来解决你的问题。例如,我会考虑研究QtConcurrent框架。或者,您也可以重新设计您的设计,以便客户端在请求缓存执行任何操作之前首先连接到缓存上的"finished“信号。如果做不到这一切,您还可以考虑依赖QMetaObject::invokeMethod函数(用于客户端或缓存)。此函数允许您使用任意泛型参数(以线程安全的方式)在任意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;
};然后将该对象从客户端传递到缓存。然后,缓存在此对象上调用invoke。
注意QPointer的使用--这为您提供了一种线程安全的方法,可以在尝试调用对象上的方法之前检查对象是否已被销毁。因为我以前也这么做过,所以我还要告诉你,Qt 4.8之前的版本有一个在多线程上下文中会导致崩溃的bug in QPointer。如果要执行此操作,请使用较新版本的Qt。
我希望这是很清楚的。
https://stackoverflow.com/questions/12009791
复制相似问题