- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在尝试通过 QWebSocket 发送和接收消息,但不确定这一切在“用户同时按下所有按钮”场景中的安全性。
想象一下:有几个按钮触发通过 QWebSocket 发送的消息,它们接收并处理响应,然后显示结果。 sendTextMessage
和 textMessageReceived
之间是否存在竞争条件,即几乎同时发送两条消息可能会触发响应混合?
我想问的是我是否需要这个:
// somewhere in initialization code, I have it in a slot connected to the QWebSocket's "connected" signal
connect(&socket, &QWebSocket::textMessageReceived, this, &client::record_response); // store the response in a member QString called "response"
connect(&socket, &QWebSocket::textMessageReceived, &wait_for_it, &QEventLoop::quit);
// somewhere after a button is pressed
mutex.lock()
socket.sendTextMessage(message);
eventLoop.exec()
QString the_response = response;
mutex.unlock()
// continue working with the_response
或者如果设置更简单(没有互斥量也没有事件循环):
// initialization after QWebSocket is connected
connect(&socket, &QWebSocket::textMessageReceived, this, &client::record_response); // store the response in a member QString
// somewhere after a button is pressed
socket.sendTextMessage(message);
// continue processing "response" immediately
在调用 sendTextMessage
之后,QString 响应
会立即“填充”吗?我不这么认为,但这意味着所有 QWebSocket
机制都是异步的,我无法在其文档中明确找到这一点。那么我应该怎么做才能防止竞争条件呢? (我能不能让它更简单,这样我就不需要任何“中间”变量,比如 response 和 the_response,或者事件循环?)
编辑 我看到了 this question (更重要的是 this answer )在侧边栏中链接,这让我想到我可以只使用 lambda 而不是整个设置,但也许将互斥锁作为一种简单但相对昂贵的方式来防止之间的串扰响应和请求。这有什么意义吗?
最佳答案
Qt 的 I/O/网络相关类(包括 QWebSocket)是异步的,以避免阻塞主线程,但绝不会向 API 用户公开它们可能在内部使用的任何多线程。因此,除非您在自己的代码中使用线程,否则只有极少数情况会使用 QMutex 或其他显式线程同步(我唯一想到的是 QtQuick 项目的自定义绘制)。
textMessageReceived
将在任何其他事件(其中的用户输入)之间按事件循环管理的顺序发出,但绝不会以并行、多线程的方式发出。
正如您已经注意到的,QWebSocket 不提供一种机制来跟踪哪个响应属于哪个请求。互斥量对您没有帮助,阻塞执行是 UI 编程中的错误方法。您不希望用户界面在等待响应时卡住。根据您的用例,您可以禁用 UI,例如在等待响应时通过模态进度弹出窗口或 setEnabled(false)(如果使用小部件),确保在 UI 等待第一个响应时不会发送第二个请求。现在这仍然比完全阻塞 UI 线程要好,后者甚至会阻止 UI 被绘制。
如果您希望 UI 保持启用状态并可能在等待对先前请求的响应时发送更多请求,则需要围绕 QWebSocket 构建自定义“请求管理器”逻辑,将响应与请求匹配,跟踪未响应请求的队列并在响应到达时通知正确的请求发送者。我的建议是遵循 QNetworkAccessManager 中也使用的命令模式(QNAM):发送请求时,向发送者返回一个 Reply 对象(在 QNAM 中,即 QNetworkReply 的作用)。发件人连接到回复的“完成”信号,一旦相应的响应到达,就会发出该信号。这样,发送方就会以事件驱动的异步方式准确接收到想要的响应,而无需任何显式等待和阻塞。
关于c++ - QwebSocket::sendTextMessage/textMessageReceived 是异步的还是我不应该理会 QMutex/QEventLoop?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36670355/
我正在使用 Qt5,QCoreApplication。为了允许可读和易于维护的代码,我需要在类/线程 A 中编写一个阻塞方法,它将发出信号,连接到不同线程 B 中的插槽,然后等待答案或超时在线程 B
我有一个必须在登录屏幕关闭之前更新的菜单屏幕。代码类似于下面的代码; emit updateMainMenuAccordingToUserRights; QCoreApplication::proce
我不确定问题的标题是否表述正确,因此为了解释我的真正意思,请考虑以下示例: 我创建了一个QApplication和一个QWidget,上面有一个QPushButton。然后,我将一个处理程序附加到来自
我有两个按钮:播放和暂停。还有我滑动条。 我想按下播放器来改变幻灯片的位置,直到发出一个事件,或者按下暂停键。为此,我正在使用 QEventLoop。 void MainWindow::slider(
我的问题很笼统,与 QT 中类 QEventLoop 的使用有关。我有两个主要问题。 问题 1) 它在 QT 内部如何工作(我主要关心的是为什么执行 QEventLoop 对象不会阻塞 QT 应用程序
我正在编写一个 Windows DLL,它可以在 QApplication 下运行,也可以在常规 Win32 应用程序下运行。我想使用需要事件循环的 Qt Networking 类。 如果在常规 Wi
QEventloop和QAbstractEventDispatcher有什么关系? Event loop is a loop that runs the event dispatcher until
我正在尝试根据特定架构验证 xml 文件。 因此,我将架构加载到 QXmlSchema 对象中。但我遇到了一些奇怪的错误。 我的代码如下所示: int main() { QUrl url("http:
我尝试使用 Qt 网络支持扩展在 Ubuntu/Linux 桌面下运行的旧程序。与这些库进行 LAN 通信需要运行 QEventLoop 的 .exec() 才能真正开始工作(即:接受连接、接收、发送
我的函数使用 QNetworkAccessManager 同时下载多个文件。然后它应该等待所有 QNetworkReply 回复完成,然后再继续其余代码。 但是我无法让 QEventLoop 处理多个
我有一个 Button 点击后连接到 myfunction,见下文。 我正在使用 QEventLoop,因为我正在等待一个事件,它会调用 _myEventLoop.exit(0); 当我连续两次单
问题 我目前正在将 FUSE 与 qt5 放在一起。 Qt 和 FUSE 之间还没有桥梁,FUSE 主线程(产生其他工作的 FUSE 线程)和 QCoreApplication 只是并排运行。 但我希
我有一个相当简单的应用程序,当我调用 QEventLoop::exec 时,它似乎在某些情况下死锁。应用程序在两种情况下调用此函数: 当某些数据到达套接字时 根据计时器事件 在这两种情况下,它都用于以
我在使用 QEventLoop 时遇到了问题。我想为我的单元测试创建一个“TimeBoundExerciser”,这样在 QEventLoop 上阻塞的 SUT 就不会阻塞其余的测试用例。具体来说
有一个包含 std::thread 的对象,我想在对象被销毁时完成。 最少的工作代码: #include #include #include struct Connector { Con
这个问题在这里已经有了答案: Why does calling quit() before exec() not quit the application? (2 个答案) 关闭 7 年前。 我创建
我正在尝试通过 QWebSocket 发送和接收消息,但不确定这一切在“用户同时按下所有按钮”场景中的安全性。 想象一下:有几个按钮触发通过 QWebSocket 发送的消息,它们接收并处理响应,然后
我读过有两种使用 QThread 的方法。 如果我有一个继承 QObject 的 Worker 类(如 http://mayaposch.wordpress.com/2011/11/01/how-to
我是一名优秀的程序员,十分优秀!