【发布时间】:2017-09-28 08:39:29
【问题描述】:
如果我有一个主线程和一个单独的永久工作线程 QThread:
// Main thread where the event loop and QCoreApplication runs.
class NetworkController : public QObject {
public:
Q_OBJECT
void connect_to_ap()
{
WifiAP *myAP = netMgr.get_best_ap();
myAP->connect("my_psk_password");
}
// This is a class from a 3rd-party library, which contains, owns
// and manages the lifetime of "WifiAP" instances.
NetworkManager netMgr;
};
// Separate thread where a state machine runs.
class StateMachineWorker : public QObject {
public:
Q_OBJECT
void on_ready_to_connect_event()
{
// HERE: How to trigger NetworkController::connect_to_ap() and
// *block* until it returns.
}
NetworkController *pNetCtrlr;
}
当状态机类进入特定状态时,它应该连接到 AP(接入点)。 NetworkController 具有连接 AP 的功能。
我正在尝试找出一种状态机可以以线程安全的方式执行此操作的方法。问题是NetworkManager 总是在更新它的WifiAP 实例列表:它们经常被创建和销毁。
StateMachineWorker 直接调用pNetCtrlr->connect_to_ap() 不是线程安全的(因为NetworkController 线程中的NetworkManager 可以同时删除WifiAP 实例)。
所以我想要在StateMachineWorker::on_ready_to_connect_event() 中以某种方式向NetworkController 发出信号以在NetworkController 自己的线程中运行其connect_to_ap() 方法,并阻止StateMachineWorker线程直到connect_to_ap() 完成它的工作。我希望状态机被阻塞的原因是,如果我没有阻塞并让它进入事件循环,它可能会收到一些事件,使其转换到另一个状态之前connect_to_ap()已经完成执行;这绝对不能发生。
用于保护NetworkManager 中WifiAP 列表的互斥锁不起作用,因为它们需要插入到第3 方库中。
【问题讨论】:
-
使用互斥锁?? ^^
-
cond_var 或 mutex 应该可以完成工作
-
@Robert 请参阅我在问题中的最后一句话。互斥锁需要位于我不想编辑的第 3 方库中。没有必要互斥锁
netMgr,因为WifiAP实例会在NetworkManager内自动删除(通过信号/插槽等等)。 -
在 StateMachineWorker 线程上使用 wait() 吗?
-
StateMachineWorker可以向NetworkController发送信号,通知它应该运行connect_to_ap,然后使用QEventLoop 阻止自己。您可以将来自NetworkController的信号连接到通知其工作结束的信号到事件循环的quit插槽,这将解除对StateMachineWorker的阻塞并让它进一步工作。有关QEventLoop用法的一些详细信息,请参阅我的this 回答。
标签: c++ multithreading qt c++11 thread-safety