我有这个qt相关的问题。QNetworkAccessManager::get()返回QNetworkReply指针。然后我可以连接到它的完成槽:
QNetworkReply* r = nam->get(url);
connect(r, SIGNAL(finished()),
this, SLOT(_finishedThisReply()));
这似乎是做事情的正确方法,特别是,使用这种方法,您可以使用相同的QNetworkAccessManager对象同时请求。然而,我们这里不是有一个竞态条件吗?如果在完成get和调用connect之间已经发送了完成的信号呢?或者QT保证这种情况不会发生?
由于您可以完全控制在其中运行的线程中发生的事情,因此由于您的代码在这里运行,因此不可能存在竞争条件。
当然,网络访问管理器的内部可能在另一个线程中运行。假设在QNetworkManager
的实现中发生了以下情况:
Thread A: QNetworkReply* r = nam->get(url);
Thread B: emit r->finished();
Thread A: connect(r, SIGNAL(finished()), ...);
那确实是个问题。唉,实现可以做其他事情:
Thread A: QNetworkReply* r = nam->get(url);
Thread B: QMetaObject::invokeMethod(r, "finished");
// equivalent to QCoreApplication::postEvent(r, new QMetaCallEvent(...))
Thread A: connect(r, SIGNAL(finished()), ...);
...
在这里,信号在应答线程内同步发出。这与第一个变量相反,在第一个变量中,信号是异步发出的。
最终,线程A的控制返回到事件循环,并且以QMetaCallEvent
的形式将跨线程方法调用发送给r
,发出信号。
我正在简化,但是QNetworkReply
的语义是第二个正确的变体的语义。它"就是好用"。没有竞争,即使网络访问管理器的实现在一个单独的线程中运行。