0

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

试图了解此类如何线程化其方法

...我理解线程必须在 qthread 的子类中的方法。并且 this 的运行实现了这个类的线程代码。并且该线程仅在调用此类对象的 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();
}

问题:线程上下文相对于它的方法意味着什么。

问题:如果在这个类的线程开始之前调用这个类的一个方法会发生什么

4

1 回答 1

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是一种方便的基于堆栈的 RAII 方法,用于处理 Qt 中的互斥锁。

我相信我在这里完全回答了你的问题,所以我会继续链接到我在另一个网站上写的RAII线程文章,以供进一步参考。

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

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 将避免共享数据和死锁的一些潜在线程问题。
于 2011-03-09T15:15:39.130 回答