在我的节目中,我分门别类。
void ManagerThread::run() {
// do a bunch of stuff,
// create some objects that should be handled by this thread
// connect a few signals/slots on the objects using QueuedConnection
this->exec(); // start event loop
}
现在,在另一个版面(即:MainThread
)中,我开始使用<代码>ManagerThread/code>和wait for its started(<>/code> sign
,此后,我着手使用应由ManagerThread
处理的信号和位置。 然而,started(>
sign is fundamental emmitted right before run()
,因此,根据阅读时间安排,我从MainThread
中失去一些信号,因为活动周期尚未开始!
(EDIT:发现,问题不是,而是信号没有及时连接,原因相同)
我可在打电话exec(
)之前发出信号,但这也引起麻烦。
是否有任何确切/简单的方法知道事件的发生已经开始?
感谢!
<>strong>EDIT2: (SOLUTION)
坦率地说,这个问题恰恰是我所说的。 活动 lo头开始就是一个问题,因为信号
解决办法is,在外围所有联系和权利之后发出另一条习俗信号。 这样,所有信号/位置都得到保证。
这是
我把我的所有法典留给了这些好奇的人,解决办法是等待<编码>instance()方法中的另一个信号。
<<>CODE>:
Many of you are saying that I cannot lose signals, so here is my whole class implementation. I will simplify it to just the bare necessities.
此处为<代码>的接口。 ManagerThread:
// singleton class
class ManagerThread: public QThread {
Q_OBJECT
// trivial private constructor/destructor
public:
static ManagerThread* instance();
// called from another thread
public:
void doSomething(QString const& text);
// emitted by doSomething,
// connected to JobHandler whose affinity is this thread.
signals:
void requestSomething(QString const& text);
// reimplemented virtual functions of QThread
public:
void run();
private:
static QMutex s_creationMutex;
static ManagerThread* s_instance;
JobHandler* m_handler; // actually handles the requests
};
一些相关的执行。 2. 创建直线区:
ManagerThread* ManagerThread::instance() {
QMutexLocker locker(&s_creationMutex);
if (!s_instance) {
// start socket manager thread, and wait for it to finish starting
s_instance = new ManagerThread();
// SignalWaiter essentially does what is outlined here:
// http://stackoverflow.com/questions/3052192/waiting-for-a-signal
SignalWaiter waiter(s_instance, SIGNAL(started()));
s_instance->start(QThread::LowPriority);
qDebug() << "Waiting for ManagerThread to start";
waiter.wait();
qDebug() << "Finished waiting for ManagerThread thread to start.";
}
return s_instance;
}
• 重新实施设置信号/位置和启动活动周期的运行:
void ManagerThread::run() {
// we are now in the ManagerThread thread, so create the handler
m_handler = new JobHandler();
// connect signals/slots
QObject::connect(this,
SIGNAL(requestSomething(QString const&)),
m_handler,
SLOT(handleSomething(QString const&)),
Qt::QueuedConnection);
qDebug() << "Starting Event Loop in ManagerThread";
// SOLUTION: Emit signal here and wait for this one instead of started()
this->exec(); // start event loop
}
Function that delegates the handling to the correct thread. This is where I emit the signal that is lost:
void ManagerThread::doSomething(QString const& text) {
qDebug() << "ManagerThread attempting to do something";
// if calling from another thread, have to emit signal
if (QThread::currentThread() != this) {
// I put this sleep here to demonstrate the problem
// If it is removed there is a large chance the event loop
// will not start up in time to handle the subsequent signal
QThread::msleep(2000);
emit(requestSomething(text));
} else {
// just call directly if we are already in the correct thread
m_handler->handleSomething(text);
}
}
Finally, here is the code from MainThread
that will fail if the event loop doesn t start in time:
ManagerThread::instance()->doSomething("BLAM!");
假设手稿只是打印出其文本,那是成功版本的:
Waiting for ManagerThread to start
Finished waiting for ManagerThread thread to start.
Starting Event Loop in ManagerThread
ManagerThread attempting to do something
BLAM!
这里是一场失败:
Waiting for ManagerThread to start
Finished waiting for ManagerThread thread to start.
ManagerThread attempting to do something
Starting Event Loop in ManagerThread
Clearly the event loop started after the signal was emitted, and BLAM never prints. There is a race condition here, that requires the knowledge of when the event loop starts, in order to fix it.
也许我没有东西,问题有些不同。
Thanks so much if you actually read all that! Phew!