理解qthread子类的run方法和线程上下文

时间:2011-03-09 13:40:20

标签: c++ multithreading qt qthread concept

我有一个有很多方法的编码器类。这是Qthread的子类。我是多线程的新手,

  

试图理解这门课是怎么回事   线程化其方法

...我理解为一个方法必须在一个qthread的子类中。并且它的运行实现了这个类的线程代码。并且只有在对此类的对象进行start方法调用时才会启动该线程。

  

问题:首先你推断出什么   从这个运行实现

void Encoder::run(void)
{
    VERBOSE(VB_DEBUG, "Encoder::run");

    if (WILL_PRINT(VB_DEBUG))
        print_stats_timer_id = QObject::startTimer(kEncoderDebugInterval);
    health_check_timer_id = QObject::startTimer(kEncoderHealthCheckInterval);

    if (init())
        exec();
    else
        VERBOSE(VB_ERROR, "Encoder::run -- failed to initialize encoder");

    QObject::killTimer(health_check_timer_id);
    if (print_stats_timer_id)
        QObject::killTimer(print_stats_timer_id);

    cleanup();
}
  

问题:线程上下文的含义   与其方法的关系。

  

问题:会发生什么情况如果有这种方法   class在此类之前调用   线程已经开始

1 个答案:

答案 0 :(得分:4)

  1. 您编写的类创建一个线程并初始化一个QObject :: timer。然后继续调用用户定义的init()函数,然后调用QThread::exec()函数。

    1. 我的猜测是你的意图是exec()将是一个用户定义的函数,其中将发生实际的工作。请注意,QThread :: exec()处理线程的Qt事件队列。
    2. 此外,在某些平台上,您可能会收到“从线程创建计时器错误”警告消息。当代码在Linux上正常运行时,我在Windows上遇到了这个错误
    3. 另外,请注意,如果您未在线程中调用QThread :: exec()函数或QApplication::processEvents(),则永远不会出现计时器。
  2. Qt中的线程上下文与任何其他线程概念相同。也就是说,所有内存都在线程代码之间共享(此时在“run()”函数中输入)。以及调用您对象的任何其他上下文。如果此对象可能在线程中执行并从线程外部访问,则必须保护共享数据。

  3. 因为所有数据都是在线程上下文之间共享的(它是一个共享内存多处理模型),所以在线程执行之前/之后/期间调用函数没有问题。鉴于:
    1. 在调用任何方法之前,对象是完全构造的。除非在线程中创建对象,否则这对线程并不特殊。
    2. 任何数据成员都使用互斥锁进行保护(我在#2中对此进行了解释)。 QMutexLocker是一种在Qt中处理互斥锁的基于RAII的方便的RAII方式。
  4. 我相信我在这里完全回答了您的问题,因此我会继续链接到我在其他网站上撰写的RAIIthreading条,仅供进一步参考。

    编辑:关于线程场景的特异性:

    class MyThreadedClass : public QThread
    {
      MyThreadClass(const boost::shared_ptr<SomeOtherClass> &t_object)
        : m_object(t_object) {}
    
      void doSomething()
      {
        // Depending on how this method was called (from main, from internal thread)
        // will determine which thread this runs on, potentially complicating thread
        // safety issues.
        m_object->someThing(); 
      }
    
      void run()
      {
        // I'm now in a thread!
        m_object->someFunction(); // oops! The call to someFunction is occurring from 
                                  // a thread, this means that SomeOtherClass must be 
                                  // threadsafe with mutex guards around shared 
                                  // (object level) data.
        // do some other stuff
      }
    };
    
    int main()
    {
      MyThreadClass thread(someobjectfromsomewhere);
      thread.start(); // MyThreadClass is now running
      thread.doSomething(); // The call to doSomething occurs from main's thread.
                            // This means 2 threads are using "thread", main 
                            // and "thread"'s thread. 
      // The call to thread.doSomething hits Thread.m_object, which means that 
      // now multiple threads are also accessing m_object ("thread" and "main").
      // This can all get very messy very quickly. It's best to tightly control 
      // how many threads are hitting an object, and how
    }
    
    • 注意:调查QFuture是一个好主意,它旨在处理这种异步任务,就像您正在查看的编码器一样 QFuture会避免一些共享数据和死锁的潜在线程问题。