我在qt应用程序中有这个类,它定义了一些数据:
class TableView:public QWidget
{
Q_OBJECT
public:TableView (QWidget * parent = 0);
std::vector < float > arr;
和一些类函数等等.. 现在我想在另一个线程中添加一个套接字服务器(可以从这个类内部),当它从套接字中重新获取某些东西时能够从该类访问数据,计算 新数据并返回。
对于我使用的测试:
//defines
DWORD WINAPI SocketHandler(void* lp);
DWORD WINAPI starttremeshserver(void* lp);
CreateThread(0,0,&starttremeshserver, (void*)csock , 0,0);
这很有效。现在我需要简单且独立于平台的东西。也许是因为我在qt工作的qthread。
所以问题是,我可以在一个可以访问类数据的类中创建一个新的线程函数。 TY
答案 0 :(得分:5)
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将使用Qt::QueuedConnection
类型重新连接所有信号槽连接。因此,当Processor
发出hasFloat
时,它将在内部导致事件在TableView
所在的线程的事件队列中排队 - 在这种情况下是GUI线程。当事件循环旋转时(这里它是应用程序的事件循环) - 它将获取事件并执行对TableView::setFloat
的调用。这可以确保对arr
数据成员的访问进行序列化,并且不可能从多个线程进行并发访问。
答案 1 :(得分:1)
Qt具有线程支持,可以找到here。
除了线程和访问数据之外,您还需要同步以获得线程安全的代码。这在linux中称为pthread mutex,在Qt中称为QMutex,如here所述。
您可以找到Qt网络原语here。
使用这些线程和网络原语的Qt实现将是可移植的,因此应该在Windows上为您工作。
关于从访问该类数据的类创建线程函数的问题,答案是肯定的。而不是创建线程函数,最好创建一个线程对象,即QThread。在创建线程对象时,您需要传递对该类实例的引用,这将允许线程访问类实例。
答案 2 :(得分:1)
我个人会寻找更高级别的套接字支持,也许是基于boost的东西,无论如何,对于你可以在C ++ 11中使用<thread>
的线程。
回答您的具体问题:
class Foo
{
private:
void spinthread()
{
thread t([this] {
this->bar = 12;
});
}
private:
int bar;
}
如果您正在使用Win32线程API,则线程proc有一个参数,您可以使用该参数在CreateThread调用期间将实例传递给它。