- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有两个对象,它们位于不同的线程中,我试图确定所使用的模式是否是线程安全的。
第一个对象是 QObject 派生的,存在于(创建于)主 Qt 线程中。该类包含一些应从 QML 调用的 Q_INVOKABLE
方法、一些定义为 signals:
的 signal*()
方法和一些 Emit *()
(普通)方法,我用作包装器来发出信号。例如:
void MyQObjectClass::EmitStatus(void) {
emit signalStatusChange(_status);
}
我通常在 QML 中监听这些信号。
第二个对象不是 QObject 派生的,存在于第二个线程 (pthread
) 中。该线程运行自己的事件循环 (libev) 并分派(dispatch)事件。我不能在此线程中使用与 Qt 相关的任何内容,因为我需要自定义 libev
事件循环。在这个对象上,我定义了一些 Notify*()
方法,这些方法将通过 libev
发送异步事件以供回调接收。
我需要能够在两个对象/线程之间进行通信,但我不确定如何安全地进行通信。
实际的设计是让pthread
线程对象直接调用不同的Emit*()
方法,这样QObject就可以正确的将信息传递给Qt/QML。如果我需要将信息从 Qt/QML 发送到 pthread
/libev
对象,我将调用(从 Qt 线程)Notify*()
方法。
阅读时Accessing QObject Subclasses from Other Threads ,它说:
QObject and all of its subclasses are not thread-safe. This includes the entire event delivery system.
但进一步指出:
On the other hand, you can safely emit signals from your QThread::run() implementation, because signal emission is thread-safe.
所以我的问题是,上面描述的设计是线程安全的吗?我能否安全地调用 myQObject->EmitMySignal()
,而后者又会调用 emit signalMySignal()
,所有这些都来自 pthread
对象?
最佳答案
我将演示如何使用事件而不是您不能使用的信号和插槽来实现您想要的(因为一侧不是 QObject
派生的)
class MyObjectClass : public QObject
{
Q_OBJECT
public:
virtual bool event(QEvent *event) override
{
bool result = true;
if(event->type() == QEvent::User+1)
emit signalStatusChange(_status);
else
result = QObject::event(event); //call direct parent's event here!
return result;
}
};
在您的另一个线程中,您将执行此操作:
MyObjectClass *p; //holds pointer to the instance in main thread
qApp->postEvent(p, new QEvent(QEvent::User+1));
这将检索指向位于主线程中的应用程序的指针,并将事件发布到其事件循环中。然而,事件将从调用中异步处理,因此行为将与您现在所做的不同。但它会更安全,恕我直言,更优雅。您可以根据需要添加任意数量的类型。如果您还没有处理事件,请不要忘记将事件传播给父级!
关于c++ - 从另一个(非 qt)线程调用 QObject 方法的线程安全性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40916479/
我想了解 Ruby 方法 methods() 是如何工作的。 我尝试使用“ruby 方法”在 Google 上搜索,但这不是我需要的。 我也看过 ruby-doc.org,但我没有找到这种方法。
Test 方法 对指定的字符串执行一个正则表达式搜索,并返回一个 Boolean 值指示是否找到匹配的模式。 object.Test(string) 参数 object 必选项。总是一个
Replace 方法 替换在正则表达式查找中找到的文本。 object.Replace(string1, string2) 参数 object 必选项。总是一个 RegExp 对象的名称。
Raise 方法 生成运行时错误 object.Raise(number, source, description, helpfile, helpcontext) 参数 object 应为
Execute 方法 对指定的字符串执行正则表达式搜索。 object.Execute(string) 参数 object 必选项。总是一个 RegExp 对象的名称。 string
Clear 方法 清除 Err 对象的所有属性设置。 object.Clear object 应为 Err 对象的名称。 说明 在错误处理后,使用 Clear 显式地清除 Err 对象。此
CopyFile 方法 将一个或多个文件从某位置复制到另一位置。 object.CopyFile source, destination[, overwrite] 参数 object 必选
Copy 方法 将指定的文件或文件夹从某位置复制到另一位置。 object.Copy destination[, overwrite] 参数 object 必选项。应为 File 或 F
Close 方法 关闭打开的 TextStream 文件。 object.Close object 应为 TextStream 对象的名称。 说明 下面例子举例说明如何使用 Close 方
BuildPath 方法 向现有路径后添加名称。 object.BuildPath(path, name) 参数 object 必选项。应为 FileSystemObject 对象的名称
GetFolder 方法 返回与指定的路径中某文件夹相应的 Folder 对象。 object.GetFolder(folderspec) 参数 object 必选项。应为 FileSy
GetFileName 方法 返回指定路径(不是指定驱动器路径部分)的最后一个文件或文件夹。 object.GetFileName(pathspec) 参数 object 必选项。应为
GetFile 方法 返回与指定路径中某文件相应的 File 对象。 object.GetFile(filespec) 参数 object 必选项。应为 FileSystemObject
GetExtensionName 方法 返回字符串,该字符串包含路径最后一个组成部分的扩展名。 object.GetExtensionName(path) 参数 object 必选项。应
GetDriveName 方法 返回包含指定路径中驱动器名的字符串。 object.GetDriveName(path) 参数 object 必选项。应为 FileSystemObjec
GetDrive 方法 返回与指定的路径中驱动器相对应的 Drive 对象。 object.GetDrive drivespec 参数 object 必选项。应为 FileSystemO
GetBaseName 方法 返回字符串,其中包含文件的基本名 (不带扩展名), 或者提供的路径说明中的文件夹。 object.GetBaseName(path) 参数 object 必
GetAbsolutePathName 方法 从提供的指定路径中返回完整且含义明确的路径。 object.GetAbsolutePathName(pathspec) 参数 object
FolderExists 方法 如果指定的文件夹存在,则返回 True;否则返回 False。 object.FolderExists(folderspec) 参数 object 必选项
FileExists 方法 如果指定的文件存在返回 True;否则返回 False。 object.FileExists(filespec) 参数 object 必选项。应为 FileS
我是一名优秀的程序员,十分优秀!