Qt 提供了你需要的一切。您的需求如下:
对类的数据成员的线程安全(序列化)访问TableView
。
网络原语。
灵活地将网络访问移至单独的线程。
您可能正在从网络接收数据,并希望更新arr
成员。你会这样做:
创建一个QObject
派生类,比如Processor
,它有一个设置网络连接的插槽(可能是一个QTcpServer
)。建立连接后,用于QTcpSocket
交换数据。确保您的所有数据处理都在类的插槽中完成。当您在向量中有要更新的新值时,只需emit
一些信号,例如hasFloat(int,float)
.
在. setFloat(int,float)
_TableView
setFloat
将信号从实例连接Processor
到您的TableView
.
此时,一切都在 GUI 线程中运行,但代码是非阻塞的,因为您从不等待网络数据;QTcpServer
您响应和发出的信号QTcpSocket
。如果你愿意,你可以这样。
Processor
如果您的基准测试显示您的主线程受 CPU 限制,则让该类在单独的线程中运行,那么这很简单:
int main(int argc, char** argv) {
bool separateThread = true;
QApplication app(argc, argv);
TableView view;
Processor proc;
connect(&proc, SIGNAL(hasFloat(int,float)), &view, SLOT(setFloat(int,float)));
QThread thread;
if (separateThread) {
thread.start();
proc.moveToThread(&thread);
}
view.show();
const bool rc = app.exec();
if (thread.isRunning()) {
thread.exit(); // tells the event loop in the thread to bail out
thread.wait(); // waits for the above to finish
}
return rc;
}
有一种误解认为跨线程传播事物会神奇地使它们变得更好。线程是特定问题的解决方案:正在完成的计算的 CPU 限制性和阻塞 API。如果您的处理是微不足道的,那么您不太可能受 CPU 限制。Qt 提供非阻塞、异步网络。因此,通常完全不需要旋转第二根线。
您必须先显示实数才能显示。否则,您正在购买线程的货物崇拜:哦,它是网络,它必须进入一个单独的线程。不,不一定。先测量。了解你在做什么。
上述代码中线程安全的原因如下:当你将Processor
实例移动到不同的线程时,Qt 会使用 type.slot 重新连接所有的信号槽连接Qt::QueuedConnection
。因此,当Processor
发出时hasFloat
,它会在内部导致一个事件在所在线程的事件队列中排队TableView
- 在这种情况下是 GUI 线程。当事件循环旋转时(这里是应用程序的事件循环)——它将接收事件并执行对TableView::setFloat
. 这确保了对arr
数据成员的访问是序列化的,并且不可能有来自多个线程的并发访问。