понимание метода запуска и контекста подкласса qthread - PullRequest
0 голосов
/ 09 марта 2011

У меня есть класс кодировщика с множеством методов. это подкласс 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();
}

Вопрос: что означает контекст потока отношение к его методам.

также

Вопрос: что произойдет, если метод этого класс называется до этого класса нить началась

1 Ответ

4 голосов
/ 09 марта 2011
  1. Класс, который вы написали, создает поток и инициализирует QObject :: timer. Затем он вызывает вызываемую пользователем функцию init (), а затем функцию QThread :: exec () .

    1. Я предполагаю, что вы предполагали, что exec () будет пользовательской функцией, в которой должна выполняться реальная работа. Имейте в виду, что QThread :: exec () обрабатывает очередь событий Qt потока.
    2. Кроме того, на некоторых платформах может появиться предупреждение «Ошибка создания таймера из потока». Я столкнулся с этой ошибкой в ​​Windows, когда код прекрасно выполнялся в Linux
    3. Также помните, что ваш таймер никогда не будет срабатывать, если вы не вызовете функцию QThread :: exec () или QApplication :: processEvents () изнутри вашего потока.
  2. Контекст потока в Qt такой же, как и любой другой концепт потока. То есть вся память распределяется между многопоточным кодом (введенным в этот момент в вашей функции «run ()»). И любой другой контекст, который вызывает ваш объект. Если этот объект когда-либо выполняется в потоке и доступен извне потока, вы должны защитить общие данные.

  3. Поскольку все данные совместно используются контекстами потоков (это модель многопроцессорной обработки с общей памятью), проблем с вызовом функций до / после / во время выполнения потока не возникает. При условии:
    1. Объект полностью построен перед вызовом любого метода. Это не обязательно для потоков, обязательно, если объект не создан в потоке.
    2. Любой элемент данных защищен блокировкой мьютекса (об этом я говорил в # 2). QMutexLocker - это удобный RAII-способ работы с мьютекс-блокировками в Qt.

Я полагаю, что я полностью ответил на ваш вопрос здесь, поэтому я продолжу ссылаться на RAII и Threading статей, которые я написал на другом сайте, просто для дальнейшего ознакомления.

Редактировать: специфичность сценариев потоков:

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 позволит избежать некоторые из потенциальных проблем с потоками общих данных и взаимоблокировок.
...