从另一个线程调用函数
Call a function from another thread
我的应用程序在启动时有多个线程。我需要线程A能够强制线程B运行一个函数(也有参数。)我试过在谷歌上搜索,但找不到我需要的东西,很多堆栈溢出的文章似乎与我正在做的事情无关。我不确定我是否只是用错了这个词,也许这就是我找不到我需要的信息的原因。如果他们的线程库中有一个选项,我愿意使用Boost,如果有,如果你能给我指明一些示例代码的方向,我可以看看它能满足我的需求。我的应用程序也已经使用了QT,尽管我从未使用过QT线程库,所以我也不知道它是否包括这一点。
基本上我需要做的就是这个。
//Thread A
void ThreadA()
{
//Do work to get data
//Pass Data to another function, and have thread B run it.
ThreadB.Run(data,arg2,arg3);
}
没有办法显式执行。您可以在线程之间传输消息,例如使用事件,这将触发对所需方法的调用。但目标线程必须处于循环中,等待消息。这是唯一一种可以强制线程进入另一个子例程的方法。
摘要示例:
// in ThreadB [the target thread]
std::vector<Message> messages;
bool wait_message;
// ...
while(wait_message) {
if(messages.size() > 0) {
// process messages
}
}
// ...
对于另一个线程:
// in ThreadA
// ...
messages.push_back(Message("call_my_method", some_data));
// ...
类别Message
(仅作为示例):
class Message {
private:
std::string _what;
void* _data;
public:
Message(const std::string& what, void* data) : _what(what), _data(data) { }
Message(const Message& inst) : _what(inst._what), _data(inst._data) { }
const std::string& what() const { return _what; }
void* data() const { return _data; }
};
仅对于函数调用,您可以使用std::function
和std::bind
,并在消息中只传递一个回调,该回调提供一些固定签名(例如void(void)
)。
我有可能使用元对象系统。但要注意后果。只要看看这个博客条目(尤其是评论中的MACRO部分)->点击我几年前,我为一个项目偷了这个部分,并喜欢它(但你必须真正了解你在做什么,以及Qt是如何处理呼叫的)
您必须定义以下MACRO,并将最后一部分扩展到您的需求:
// HELPER MACROS (from
// Just a helper macro:
#define NO_RETURN_VALUE
// This does the real work:
#define THREAD_MAGIC(targetThread, returnValue, args)
if(QThread::currentThread() != targetThread->thread())
{
QString slotName = __FUNCTION__;
slotName.remove(QRegExp("^.*::"));
bool ret = metaObject()->invokeMethod(this,
qPrintable(slotName), Qt::QueuedConnection,
args.count() >= 1 ? args[0] : QGenericArgument(0),
args.count() >= 2 ? args[1] : QGenericArgument(0),
args.count() >= 3 ? args[2] : QGenericArgument(0),
args.count() >= 4 ? args[3] : QGenericArgument(0),
args.count() >= 5 ? args[4] : QGenericArgument(0),
args.count() >= 6 ? args[5] : QGenericArgument(0),
args.count() >= 7 ? args[6] : QGenericArgument(0),
args.count() >= 8 ? args[7] : QGenericArgument(0),
args.count() >= 9 ? args[8] : QGenericArgument(0),
args.count() >= 10 ? args[9] : QGenericArgument(0));
if(!ret)
{
qFatal(qPrintable(__FUNCTION__ +
QString(" Could not call QMetaObject::invokeMethod(). "
"Check your argument list quantity and types.")));
}
return returnValue;
}
#define MAKE_THREAD_SAFE_0(TargetThread, returnValue)
do {
QList<QGenericArgument> args;
THREAD_MAGIC(TargetThread, returnValue, args);
} while (0);
#define THREAD_MAGIC_1(TargetThread, returnValue, ArgType1, ArgName1)
do {
QList<QGenericArgument> args = QList<QGenericArgument>() <<
Q_ARG(ArgType1, ArgName1);
THREAD_MAGIC(TargetThread, returnValue, args);
} while (0);
#define THREAD_MAGIC_2(TargetThread, returnValue, ArgType1, ArgName1, ArgType2, ArgName2)
do {
QList<QGenericArgument> args = QList<QGenericArgument>() <<
Q_ARG(ArgType1, ArgName1) <<
Q_ARG(ArgType2, ArgName2);
THREAD_MAGIC(TargetThread, returnValue, args);
} while (0);
现在你必须实现你的功能,例如
void ThreadClass::fn(const QString& user_, const QString& pwd_)
{
THREAD_MAGIC_2(this, NO_RETURN_VALUE, QString, user_, QString, pwd_);
// ... implementation of the function
}
正如我已经说过的:这不是我的主意——这要归功于戴夫·史密斯。
我在R.R has environment()中实现了这一点。因此,您必须使用未来或承诺在不同的环境中执行。我认为环境是依赖于线程的,不确定完整的机制,但未来的对象将执行并返回分配给它的值()。
- 函数调用中参数的顺序重要吗
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 变量没有改变?通过向量的函数调用
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 是否有C++编译器选项允许激进地删除所有函数调用,并将参数传递给具有空体的函数
- 我知道函数调用中存在歧义.有没有办法调用foo()函数
- 模板函数调用
- 获取从C++中同一类中的构造函数调用的方法返回的值
- 析构函数调用
- 成员函数调用和C++对象模型
- 使用共享指针的函数调用,其对象应为 const
- C++:编译时检查匹配的函数调用对?
- 函数调用C++中的参数太少
- 来自 DLL 的函数调用 [表观调用的括号前面的表达式必须具有(指向-)函数类型]
- 返回指向对象的指针的函数调用是否为 prvalue?
- C++ 如何重载 [] 运算符并进行函数调用
- 代码的效率. 转到和函数调用
- 是同一作用域的函数部分中的函数调用
- 如何封装一个函数,以便它只能由同一类中的一个其他函数调用?
- 类型擦除的std::function与虚拟函数调用的开销