qt类中的线程

时间:2012-06-04 08:58:54

标签: c++ multithreading qt

我在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

3 个答案:

答案 0 :(得分:5)

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

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

  2. 网络原语。

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

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

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

    2. setFloat(int,float)中添加TableView个广告位。

    3. 将来自setFloat实例的Processor信号连接到您的TableView

    4. 此时,所有内容都在GUI线程中运行,但代码是非阻塞的,因为您从不等待网络数据;您对QTcpServerQTcpSocket发出的信号做出回应。如果你愿意,你可以这样离开。

      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调用期间将实例传递给它。