Использование пользовательских событий в QT4 - PullRequest
1 голос
/ 24 декабря 2009

У меня есть приложение, которое имеет индикатор выполнения и порождает рабочий поток, чтобы выполнить некоторую работу и сообщить о прогрессе. Класс диалога переопределяет метод customEvent, так что я могу обрабатывать события, которые передаются в поток графического интерфейса через рабочий поток. До того, как я использовал производный класс QThread в качестве рабочего потока, я изменил его на использование ACE_Thread_Manager-> spawn () со статической функцией для рабочего.

Проблема появляется, когда я запускаю приложение и нажимаю кнопку, чтобы рабочий порождался и начинал делать работу. Когда он посылает сигнал для увеличения индикатора выполнения, я получаю следующие ошибки, записываемые в стандартный вывод.

QPixmap: использование пиксельных карт вне потока GUI небезопасно

Это, кажется, происходит, когда вызывается progressBar-> setValue (). Таким образом, кажется, что настройка индикатора выполнения происходит в другом потоке, чем основной поток графического интерфейса. Мне неясно, как это возможно. У меня сложилось впечатление, что у меня есть основной поток графического интерфейса с моим графическим интерфейсом, а метод customEvent находится в том же потоке, а рабочий находится в собственном потоке. Это предположение неверно? И есть ли разница при использовании производного класса QThread от статического метода run_svc?

Любая помощь будет оценена. Ниже приведены фрагменты кода для обработчика customEvent, run_svc и кода обработчика кнопки. Код прилагается.

void MyDlgEx::customEvent(QEvent * e)
{
    if (e->type() == IdNumOperations)
    {
        NumOperations* pEvt = static_cast<NumOperations*>(e); 
        _steps = 0; 
        cout << "Num Operations = " << pEvt->operations() << endl; 
    }
    else if (e->type() == IdStep)
    {
        if (_steps % 10 == 0)
        {
            cout << "Step++ = " << _steps << endl; 
        }

        _steps++;  
        _progressBar->setValue(_steps); 
    }
}

void* MyDlgEx::run_svc(void* args)
{
    auto_ptr<ThreadArgs> thread_args(static_cast<ThreadArgs*>(args)); 
    QApplication::sendEvent((QObject*)thread_args->m_pDlg, new NumOperations(300)); 

    // does some work that takes time -- ommitted for clarity 
    // called in a loop
    QApplication::sendEvent((QObject*)thread_args->m_pDlg, new Step());

    QApplication::sendEvent((QObject*)thread_args->m_pDlg, new Completed()); 

    return 0; 
}

обработчик кнопок Закомментированы строки, где я использовал класс QT, производный от QThread. Использование ACE должно порождать поток, который обнаружил эту проблему.

void MyDlgEx::btnShowProgress_clicked()
{
    //_pProc = new ProcessThread(this); 
    //_pProc->run();

    auto_ptr<ThreadArgs> thread_args(new ThreadArgs(this));
    if (ACE_Thread_Manager::instance()->spawn(
                MyDlgEx::run_svc,
                static_cast<void*>(thread_args.get()), 
                THR_DETACHED | THR_SCOPE_SYSTEM) == -1)
        cout << "Failed to spawn thread." << endl; 

    thread_args.release(); 
}

1 Ответ

4 голосов
/ 24 декабря 2009

Попробуйте вызвать QApplication :: postEvent (...) вместо QApplication :: sendEvent (). В документах говорится, что sendEvent отправляет событие напрямую, что означает, что он вызывает функцию customEvent () непосредственно из другого потока. postEvent () добавляет событие в очередь событий, откуда оно впоследствии может быть отправлено в customEvent () главным циклом событий GUI.

То, что функция customEvent () является членом объекта, созданного в основном потоке графического интерфейса, не означает, что другой поток не может вызвать функцию. Я считаю, что это то, что происходит, когда вы вызываете QApplication :: sendEvent () из другого потока.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...