Russian Qt Forum
Ноябрь 25, 2024, 08:41 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Непонятно поведение потока.  (Прочитано 8398 раз)
west
Гость
« : Ноябрь 23, 2008, 01:07 »

Столкнулся тут с такой ситуацией. Правил, правда, чужой код, но суть следующая. В проге есть функция (чего делает точно не знаю, память гоняет туда-сюда), которая вешает ГПИ минут на 15. Организую для нее поток, прога выполняется корректно, но ГПИ все равно виснет на те же 15 минут. Проверяю, стартует ли нить с помощью top`а и ps`а. Нитка выполняется и завершается корректно, но ГПИ при этом или висит, или в глубоком тормозе. В топе отжирает 97-99 процентов CPU. В ps`е статус нитки R+, а вот у ГПИ-шного процесса S+. Чего-то никогда такого не наблюдал. Даже если нить забирала много ресурсов, ГПИ был доступен, а тут реально висяк, элементы UI даже не перерисовываются. На нить же не повесить приоритеты? Есть у кого какие мысли?
Linux(MCBC), Qt3 (потоки тоже qt). lock()`и отсутствуют. Аппаратная платформа SPARC аж на 4-х процах, Эльбрус родной т.е.
Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #1 : Ноябрь 23, 2008, 04:18 »

что такое ГПИ?
может в Qt3 можно приоритет потоку задать? (в 4-ке можно+)
Записан

Юра.
novak
Гость
« Ответ #2 : Ноябрь 23, 2008, 08:49 »

что такое ГПИ?
Судя по всему, GUI. В виде "графический пользовательский интерфейс".
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #3 : Ноябрь 23, 2008, 15:35 »

2 west: покажи код потока
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
BRE
Гость
« Ответ #4 : Ноябрь 23, 2008, 16:25 »

2 west: Желательно глянуть и как поток запускается/останавливается, нет ли там wait'ов каких.
Записан
west
Гость
« Ответ #5 : Ноябрь 24, 2008, 11:05 »

Выкладываю немного в сокращенном виде код. Кстати, неполенился перетащить на ALT4.0 под intel, все работает... Надо рыть значит где-то в другом месте.
Это описание класса управления потоком, ( класс разрабатывал специально для удобства применения в чужом коде):
Код:

typedef void(QObject::*threadFunction)();

class K_ThreadManager : private QObject, public QThread
{
    Q_OBJECT
protected:

public:
    K_ThreadManager(QObject *parent, const char *name = 0);
    ~K_ThreadManager();
    void initApplyFunction(threadFunction func);
    void apply();

protected:
    void customEvent(QCustomEvent *e);
    void run();

private:
    threadFunction applyFunction;

signals:
    void closeManagerThread(K_ThreadManager*);
};

#endif
Это его реализация:
Код:
#include "k_threadmanager.h"
#include "qapplication.h"

K_ThreadManager::K_ThreadManager(QObject *parent, const char *name)
        : QObject(NULL, name), QThread()
{
    connect(this, SIGNAL(closeManagerThread(K_ThreadManager*)), parent, SLOT(slotOnEndingThread(K_ThreadManager*)));
    applyFunction = NULL;
}


K_ThreadManager::~K_ThreadManager()
{
}

void K_ThreadManager::customEvent( QCustomEvent * e )
{
    switch (e->type())
    {
    case THREAD_MANAGER_FINISHED:
        applyFunction = NULL;
        emit closeManagerThread(this);
        break;
    default:
        break;
    }
}

void K_ThreadManager::run()
{
    if (applyFunction != NULL)
        (this->*(applyFunction))();
    QCustomEvent* event = new QCustomEvent(THREAD_MANAGER_FINISHED);
    event->setData(this);
    postEvent(this, event);
}

void K_ThreadManager::initApplyFunction(threadFunction func)
{
    applyFunction = func;
}

void K_ThreadManager::apply()
{
    start();
}

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

void  AnyData::slotBuildModel()
{
        K_ThreadManager* thread = new K_ThreadManager(this,"build");
        thread->initApplyFunction((threadFunction)(&AnyData::startBuild));
        thread->apply();
}


void AnyData::startBuild()
{
        выполняются долгие нудные операции, но точно без lock и wait
        ...

}

void AnyData::slotOnEndingThread(K_ThreadManager*)
{
        //выполняем то, что были должны после startBuild
}
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #6 : Ноябрь 24, 2008, 11:59 »

Ну собственно говоря ничего удивительного. Замораживание интерфейса происходит из-за вызова метода applyFunction в K_ThreadManager::run(). applyFunction (а это AnyData::startBuild) создаеться\находиться\выполняеться в главном потоке. в доп. потоке вы только вызываете этот метод. ЧТобы достить эелаемого результета, должно быть что-то следующее:

Код
C++ (Qt)
void K_ThreadManager::run()
{
   AnyData data;
   data.startBuild();
 
   QCustomEvent* event = new QCustomEvent(THREAD_MANAGER_FINISHED);
   event->setData(this);
   postEvent(this, event);
}

При условии что AnyData не являеться гуи класом и в startBuild() непроисходит обращения к гую.
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
west
Гость
« Ответ #7 : Ноябрь 24, 2008, 12:41 »

Често говоря я так не думаю. Или не очень понимаю
Цитировать
создаеться\находиться\выполняеться в главном потоке
- Вы имеете ввиду объектный код функции?
Какая разница какая функция (с точки зрения где она находится) выполняется в потоке. Да и закоментировал сейчас тело startBuild(), и воткнул туды while бесконечный. Не виснет гуи. Надо похоже ковырять глубже юзерский код, чего там они наваяли за расчеты... Может блокирующий вызов где нибудь спрятался? Почему на Intel архитектуре работает, а на Sparc нет?
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #8 : Ноябрь 24, 2008, 13:01 »

Объект AnyData создался в главном потоке, метод startBuild также находиться в главном потоке. Вызов этого метода происходит в доп потоке, но выполняеться он в главном, поэтому гуй умирает. Проверьте это при помощи QThread::currentThread() добавив вызовы в K_ThreadManager::run() и в AnyData::startBuild()
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
west
Гость
« Ответ #9 : Ноябрь 24, 2008, 14:53 »

Ну я проверил.
Цитировать
Проверьте это при помощи QThread::currentThread() добавив вызовы в K_ThreadManager::run() и в AnyData::startBuild()
идентификаторы совпадают. т.е. Функция выполняется в потоке. Для точности воткнул еще QThread::currentThread() в void  AnyData::slotBuildModel(), до создания объекта thread, идентификатор гуевой нитки отличен от полученного в run() и в startBuild().
Все нормально, функция выполняется в потоке. Гемор в чем-то другом.
Записан
SASA
Гость
« Ответ #10 : Ноябрь 24, 2008, 16:15 »

В Qt 4.4 есть QtConcurrent. Решает те же задачи. Может посмотреть там и списать Улыбающийся
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #11 : Ноябрь 24, 2008, 16:34 »

Ну я проверил.
Цитировать
Проверьте это при помощи QThread::currentThread() добавив вызовы в K_ThreadManager::run() и в AnyData::startBuild()
идентификаторы совпадают. т.е. Функция выполняется в потоке. Для точности воткнул еще QThread::currentThread() в void  AnyData::slotBuildModel(), до создания объекта thread, идентификатор гуевой нитки отличен от полученного в run() и в startBuild().
Все нормально, функция выполняется в потоке. Гемор в чем-то другом.

Кстате да, я был неправ. Я состряпал примерчик - все работает, гуй не замораживаеться. А что происходит в startBuild()?
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
west
Гость
« Ответ #12 : Ноябрь 24, 2008, 23:53 »

Да там без поллитры не разобрать. Я вот и пытаюсь понять в теории, что там может быть такого, что вот такое получается Непонимающий. И исходя из теории проверять методом исключения. Из-за чего поток может вешать гуй?

Вообще-то, там математические алгоритмы по расчету моделей поверхностей объетов сложных  форм. Работают с ОП только, но выделяют ее до фига, и не вседа корректно.
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #13 : Ноябрь 25, 2008, 12:59 »

А из главного потока точно никто не дергает метод startBuild() когда он выполняеться в вспомогательном потоке?

ЗЫ: В вашей реализации лучше защитить мютексом  startBuild(), т.к. он не являеться потокобезопасным. Возможно главный поток пытаеться выполнить startBuild() в то время как этот же метод выполняетья в вспомогательном потоке. Попробуй сделать так:

Код
C++ (Qt)
void AnyData::startBuild()
{
   bool res = m_mutex.tryLock();
   if (!res) return;
 
   //do_something
 
   m_mutex.unlock();
}
« Последнее редактирование: Ноябрь 25, 2008, 14:28 от pastor » Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
west
Гость
« Ответ #14 : Ноябрь 25, 2008, 14:20 »

Цитировать
лучше защитить мютексом  startBuild(), т.к. он не являеться потокобезопасным
Кстати да!
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.109 секунд. Запросов: 23.