qt类内的线程 [英] Threads inside a qt class

查看:355
本文介绍了qt类内的线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在qt应用程序中有一个此类,该类定义了一些数据:

I have this class inside a qt application that has some data defined:

class TableView:public QWidget 
{
  Q_OBJECT

  public:TableView (QWidget * parent = 0);

  std::vector < float >  arr;

以及一些类函数等等. 现在,我想在另一个线程中添加一个套接字服务器(可能从此类内部),当它从套接字中获取某些内容时,该服务器能够访问此类的数据,计算 新数据并返回.

and some class functions and so on.. Now I want to add a socket server in another thread (posibly from inside this class) that is able to access data from this class when it recives something from the socket, calculate new data and return.

我使用的测试:

  //defines
  DWORD WINAPI SocketHandler(void* lp);
  DWORD WINAPI starttremeshserver(void* lp);


  CreateThread(0,0,&starttremeshserver, (void*)csock , 0,0);

这有效.现在,我需要一些简单且与平台无关的东西.也许与qthread有关,因为我在qt工作.

This works. Now I need something easy and platform independent. Maybe something with qthread since I am working in qt.

所以问题是,我可以在一个可以访问类数据的类中创建一个新的线程函数. ty

So the question is, can I make a new thread function inside a class that can access class data. ty

推荐答案

Qt提供了您所需的一切.您的需求如下:

Qt provides everything you need. Your needs are as follows:

  1. TableView类的数据成员的线程安全(序列化)访问.

  1. Thread-safe (serialized) access to the data members of the TableView class.

网络原语.

将网络访问权限移至单独线程的灵活性.

Flexibility to move network access to a separate thread.

您可能正在从网络接收数据,并想更新arr成员.您可以这样做:

You are probably receiving data from the network, and want to update the arr member. You'd do it like so:

  1. 创建一个QObject派生的类,例如Processor,该类具有用于设置网络连接的插槽(可能是QTcpServer).连接后,使用QTcpSocket交换数据.确保所有数据处理均在该类的插槽中完成.当向量中有新值要更新时,只需emit一些信号,例如hasFloat(int,float).

  1. Create a QObject-derived class, say Processor, that has a slot that sets up the network connection (probably a QTcpServer). Upon a connection, use QTcpSocket to exchange data. Make sure all your data handling is done in slots in the class. When you have new values to update in the vector, simply emit some signal, like hasFloat(int,float).

TableView中添加一个setFloat(int,float)插槽.

setFloat信号从Processor实例连接到您的TableView.

Connect the setFloat signal from the instance of Processor to your TableView.

这时,所有内容都在GUI线程中运行,但是由于您从未等待网络数据,因此代码是非阻塞的.您响应QTcpServerQTcpSocket发出的信号.您可以根据需要保留它.

At this point, everything runs in the GUI thread, but the code is non-blocking since you never wait for network data; you respond to the signals emitted by QTcpServer and QTcpSocket. You can leave it like that if you wish.

如果Processor类在单独的线程中运行,则如果基准测试表明您的主线程受CPU约束,那么这很简单:

Having the Processor class run in a separate thread, if your benchmarking shows that your main thread is CPU bound, is then trivial:

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提供了非阻塞的异步联网.因此,通常完全不需要旋转第二个线程.

There's this misconception that spreading things across threads somehow magically makes them better. Threads are a solution to a particular problem: CPU-boundedness of the computations being done, and blocking APIs. If your processing is trivial, you are not likely to be CPU bound. Qt provides nonblocking, asynchronous networking. Thus, usually, spinning a second thread is entirely unnecessary.

您必须先显示实数,否则显示您.否则,您将成为货运线程崇拜的一部分:哦,这是网络,它必须进入一个单独的线程.不,不是必须的.首先测量.了解您在做什么.

You must show real numbers first to show you otherwise. Else you're buying into the cargo cult of threading: oh, it's networking, it must go into a separate thread. Nope, not necessarily. Measure first. Understand what you're doing.

以上代码中的线程安全性原因如下:当将Processor实例移至其他线程时,Qt将使用Qt::QueuedConnection类型重新连接所有信号插槽连接.因此,当Processor发出hasFloat时,它将在内部导致事件在TableView所在的线程(在本例中为GUI线程)的事件队列中排队.当事件循环旋转时(这里是应用程序的事件循环),它将拾取事件并执行对TableView::setFloat的调用.这样可以确保对arr数据成员的访问被序列化,并且不可能从多个线程进行并发访问.

The reason for thread safety in the above code is as follows: when you move the Processor instance to a different thread, Qt will reconnect all signal-slot connections using Qt::QueuedConnection type. Thus, when Processor emits hasFloat, it will internally cause an event to be queued in the event queue of the thread where TableView lives -- the GUI thread, in this case. When the event loop spins (here it'd be the application's event loop) -- it'll pick up the event and execute a call to TableView::setFloat. This ensures that the access to the arr data member is serialized and there are is no possibility of concurrent access from multiple threads.

这篇关于qt类内的线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆