0

我在一个定义了一些数据的 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 有关。

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

4

3 回答 3

5

Qt 提供了你需要的一切。您的需求如下:

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

  2. 网络原语。

  3. 灵活地将网络访问移至单独的线程。

您可能正在从网络接收数据,并希望更新arr成员。你会这样做:

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

  2. 在. setFloat(int,float)_TableView

  3. 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数据成员的访问是序列化的,并且不可能有来自多个线程的并发访问。

于 2012-06-04T13:52:09.417 回答
1

Qt 有线程支持,可以在这里找到。

除了线程和访问数据之外,您还需要同步线程安全代码。这在 linux 中称为 pthread mutex,在 Qt 中称为 QMutex,如此处所述

您可以在此处找到 Qt 网络原语。

使用这些线程和网络原语的 Qt 实现将是可移植的,因此应该在 Windows 上为您工作。

关于从访问该类数据的类创建线程函数的问题,答案是肯定的。与其创建线程函数,不如创建一个线程对象,即QThread。创建线程对象时,您需要传递对所述类的实例的引用,这将允许线程访问类实例。

于 2012-06-04T09:10:21.073 回答
1

我个人会寻找更高级的套接字支持,也许是基于 boost 的东西,无论如何你可以<thread>在 C++11 中使用线程。

要回答您的具体问题:

class Foo
{
private:
    void spinthread()
    {
        thread t([this] { 
            this->bar = 12;
        });
    } 

private:
   int bar;
}

如果您使用的是 Win32 线程 API,则 thread proc 有一个参数,您可以使用该参数在 CreateThread 调用期间将您的实例传递给该参数。

于 2012-06-04T09:11:20.013 回答