Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > [Qt] Возможны ли тут проблемы с многопоточностью?


Автор: Elfet 1.5.2010, 23:53
Всем привет!

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

У меня есть некий класс унаследованный от QThread, в нём такая функция:
Код

void IterationThread::run()
{
    is_runing = true;

    boost::shared_ptr<Solver> solver = sflib->GetSolver().lock();

    while(solver->Iteration(i))
    {
        emit Progress(i);

        if(!is_runing)
        {
            return;
        }
    }

    emit Finished();
}


В ней я вызываю итерации: solver->Iteration(i), в них происходит решение и заполнение неких величин varsIn. 

Затем посылается сигнал emit Progress(i) - где происходит перерисовка графиков, сетки и прочие изменения в интерфейсе. Данные берутся из varsIn. 

Так вот программа иногда начинает вылетать при перерисовке сетки на вот этой вот строчке:
Код

if(element->varsIn.size() != 0)


Может ли быть это связанно с многопоточностью? Если да - то как решить?  Возможно нужно после посылки сигнала emit Progress(i) подождать когда он отработает и только потом переходить к сл итерации? Как можно это сделать? Какие другие варианты?

Заранее спасибо!

Автор: borisbn 2.5.2010, 08:06
Всё зависит от того, как ты сделал connect сигнала Progress, и какого типа у тебя i. А вообще IMHO очень мало данных для анализа. Выложи исходники

Автор: Elfet 2.5.2010, 10:18
i - просто int. Соединил при помощи connect. Все исходники можно найти тут:
http://code.google.com/p/smart-flow/source/browse/#svn/trunk

Функция solver->Iteration(int) находится здесь: http://code.google.com/p/smart-flow/source/browse/trunk/SmartFlowLib/Source/Solvers/Solver.cpp

Класс-наследник от Qthread: 
http://code.google.com/p/smart-flow/source/browse/trunk/SmartFlow/IterationThread.h
http://code.google.com/p/smart-flow/source/browse/trunk/SmartFlow/IterationThread.cpp

Соединяю в это файле, в конструкторе формы (строка 89): http://code.google.com/p/smart-flow/source/browse/trunk/SmartFlow/mainwindow.cpp

Слот принимающий сигнал (функция void MainWindow::ProgressIteration(int value), начиняющуюся со строки 27)  : http://code.google.com/p/smart-flow/source/browse/trunk/SmartFlow/mainwindow_menu.cpp

Код по отрисовки интерфейса (программу выкидывает на 283 строке): http://code.google.com/p/smart-flow/source/browse/trunk/SmartFlow/Renders/Render3D.cpp#238

Добавлено через 2 минуты и 54 секунды
Очень прошу помочь! Диплом горит!  smile 

Автор: Elfet 2.5.2010, 18:17
Можно ли сделать как-нибудь что бы интерфейс имел бы более низкий приоритет, мне важно что бы решение не прерывалось. 

Автор: borisbn 2.5.2010, 19:31
Кода очень много, разбираться во всём - IMHO твоё дело. Можно попробовать для проверки виновата ли многопоточность соеденить сигнал со слотом через Qt::BlockingQueuedConnection
Код

connect(iterationThread, SIGNAL(Progress(int)), this, SLOT(ProgressIteration(int)), Qt::BlockingQueuedConnection );

В этом случае отрисовка будет происходить последовательно с обработкой.
Если перестанет вылетать - то виновата многопоточность, т.е. при отрисовке параллельно используются данные, изменяемые при обработке. Эти данные необходимо будет "лочить". QMutex'ом например

Автор: Elfet 2.5.2010, 20:01
borisbn, ясно. Спасибо. А можно ли лочить при помощи boost::mutex? (правда там я нашёл только функции lock() и unlock() - как проверить что данные не залочены? можете дать ссылку на какой-нибудь хороший примерsmile

Добавлено через 9 минут и 9 секунд
С этим перестало падать: Qt::BlockingQueuedConnection - значит много поточность.

Автор: borisbn 2.5.2010, 22:01
Цитата(Elfet @  2.5.2010,  20:01 Найти цитируемый пост)
А можно ли лочить при помощи boost::mutex?

Можно чем угодно. boost::mutex ничем не лучше и не хуже других

Цитата(Elfet @  2.5.2010,  20:01 Найти цитируемый пост)
как проверить что данные не залочены?

А зачем ? Если ты делаешь lock, то эта функция не отдаст тебе управление, пока тот, кто захватил данные с помощью lock не отпустит их с помощью unlock

Код

void foo1()
{
    m_locker->lock(); // отсюда не выйдет, пока (1)
    // работа с данными
    m_locker->unlock();
// (2)
}

void foo2()
{
    m_locker->lock(); // отсюда не выйдет, пока (2)
    // работа с данными
    m_locker->unlock();
// (1)
}

Автор: Elfet 2.5.2010, 23:33
ясно, спасибо! 

ещё заметил странную штуку, заменил функцию size(), на empty() - стало меньше вылетать.

Автор: borisbn 3.5.2010, 00:30
Цитата(Elfet @  2.5.2010,  23:33 Найти цитируемый пост)
стало меньше вылетать

Поверь опыту, "меньше вылетать" - это плохо (как бы это не парадоксально звучало). Идеально - это когда вылетает всегда: быстро находишь и исправляешь ошибку. Если вылетает не всегда, но часто - тоже неплохо: не очень быстро, но найдёшь ошибку и исправишь. Когда вылетает очень редко - плохо: будешь очень долго искать ошибку или ситуацию, которая приводит к ошибке.

Автор: Elfet 3.5.2010, 11:46
borisbn, ага. Пока пожалуй оставлю  Qt::BlockingQueuedConnection, потом попробую mutex приделать.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)