我的应用程序在启动时有多个线程。我需要线程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);
}
答案 0 :(得分:3)
没有办法明确地做到这一点。您可以在线程之间传输邮件,例如使用events,这将触发调用所需的方法。但是目标线程必须处于循环中,等待消息。这是你可以强制线程进入另一个子程序的唯一方法。
抽象示例:
// 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)
)。
答案 1 :(得分:0)
我可以使用metaobject系统。但要注意后果。 只需看一下这篇博客文章(特别是评论中的MACRO部分) - &gt; click me 几年前我为一个项目偷了这个部分并喜欢它(但你必须真正了解你在做什么以及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
}
正如我已经说过的那样:这不是我的想法 - 归功于Dave Smith。
答案 2 :(得分:0)
我让它在 R 中工作。R 有 environment()。因此,您必须使用 future 或 promise 在不同的环境中执行。我认为环境是线程相关的,不确定完整的机制,但未来的对象将执行并返回分配给它的 value()。