crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

> deadlock
zss
  опции профиля:
сообщение 24.6.2009, 15:00
Сообщение #1


Участник
**

Группа: Участник
Сообщений: 112
Регистрация: 9.6.2009
Пользователь №: 815

Спасибо сказали: 0 раз(а)




Репутация:   0  


ситуация следующая.

Есть QMainWidow у которого есть потоковый метод. Он крутиться по флагу, вычитывает данные и посылает событие.

void QMainWindow::start()
{
    ...
    m_stopped = false;
    thread->start();
    ...
}
void QMainWindow::stop()
{
    ...
    m_stopped = true;
    thread->wait();
    ...
}

void QMainWindow::execute()
{
    while (!m_stopped)
    {
        // read data
        QCoreApplication::postEvent(new MyEvent(mydata));
    }
}


так вот иногда происходит висяк. Преположение в том, что customEvent для QMainWindow
работает в первичном потоке и stop() тоже работает в первичном потоке.

Так вот если я выставил флаг и жду, то первичный поток блокируется.
В этот момент мой поток прочитал данные, и пытается послать событие.

Может ли в данном случае быть deadlock или postEvent отработает всегда ?
Если так, то где может быть висяк и как его разрулить ?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
2 страниц V   1 2 >  
Начать новую тему
Ответов (1 - 9)
BRE
  опции профиля:
сообщение 24.6.2009, 15:19
Сообщение #2


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Что-то я не соображу, где "первичный" поток, а где "вторичный"? :blink:
Что написано в методе run "вторичного" потока, как и где вызывается QMainWindow::execute()?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
SABROG
  опции профиля:
сообщение 24.6.2009, 16:01
Сообщение #3


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Висяк из-за того, что ты "захламляешь" очередь событий.

    while (!m_stopped)
    {
        // read data
        QCoreApplication::postEvent(new MyEvent(mydata));
    }


Тут в любом случае sleep()'a не хватает.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
zss
  опции профиля:
сообщение 24.6.2009, 16:03
Сообщение #4


Участник
**

Группа: Участник
Сообщений: 112
Регистрация: 9.6.2009
Пользователь №: 815

Спасибо сказали: 0 раз(а)




Репутация:   0  


не - sleep есть (код не целиком)
более того - выполнение события ожидается через QMutex/QWaitCondition
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 24.6.2009, 16:07
Сообщение #5


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(SABROG @ 24.6.2009, 17:01) *
Висяк из-за того, что ты "захламляешь" очередь событий.

Не факт, может чтение раз в секунду происходит.

Цитата(SABROG @ 24.6.2009, 17:01) *
Тут в любом случае sleep()'a не хватает.

Возможно, он процессорное время на mutex'ах отдает, внутри чтения данных.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
SABROG
  опции профиля:
сообщение 24.6.2009, 16:07
Сообщение #6


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


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

void QMainWindow::stop()
{
    ...
    m_stopped = true;
    thread->wait();
    ...
}


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

Цитата(zss @ 24.6.2009, 16:00) *
так вот иногда происходит висяк


Я ведь правильно понимаю, гуй висит?

Сообщение отредактировал SABROG - 24.6.2009, 16:09
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
zss
  опции профиля:
сообщение 24.6.2009, 16:15
Сообщение #7


Участник
**

Группа: Участник
Сообщений: 112
Регистрация: 9.6.2009
Пользователь №: 815

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(BRE @ 24.6.2009, 17:07) *
А тут висяк вполне может быть, если устройство с которого читаешь долго ничего не возвращает и до проверки твоего флага m_stopped дело не доходит. При этом естессно и гуй висит.


ладно - тогда подробнее

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

Пример
void stop()
{
   stopThread->start();
   stopThread->wait();
}
void funcStopThread ()
{
    m_stopped = true;
    readThread->wait();
}
void readThread()
{
    while(!m_stopped)
    {
        // read data
        QCoreApplication::postEvent(...);
        Sleep(1000);
    }
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
SABROG
  опции профиля:
сообщение 24.6.2009, 16:29
Сообщение #8


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


В итоге у тебя 3 потока: основной, читающий с устройства и поток, который ждет завершения потока считывающего с устройства. Тогда ждать завершения надо в run() второго потока. Но это странно.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 24.6.2009, 16:31
Сообщение #9


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(zss @ 24.6.2009, 17:15) *
поток читает и посылает события. Он проверяет завершение на флаге.
Первичный поток хочет его остановить. Он запускает поток, в котором выставляется флаг и ожидается
завершение читающего потока. Но т.к. обработка событий в первичном потоке, то где-го висяк.
Причем он не всегда.

А для чего такие сложности со вторым останавливающим потоком?

Как мне кажется, тебе нужно сокращать время отклика потока для чтения, т.е. ты флаг остановки установил, этот поток должен завершиться как можно быстрее. Тогда и wait будет отрабатывать быстро, или не использовать wait, а ждать от потока сигнал finised? Тут от твоей задачи зависит.

void readThread()
{
    for(;;)
    {
        if( m_stopped )
            break;
        // read data

        if( m_stopped )
            break;
        QCoreApplication::postEvent(...);

        if( m_stopped )
            break;
        Sleep(1000);
    }
}


Да, на sleep(1000) будет секундная задержка проверки флага. Здесь нужно что то придумать.

Сообщение отредактировал BRE - 24.6.2009, 16:33
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
zss
  опции профиля:
сообщение 24.6.2009, 16:39
Сообщение #10


Участник
**

Группа: Участник
Сообщений: 112
Регистрация: 9.6.2009
Пользователь №: 815

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(zss @ 24.6.2009, 17:15) *
Тогда ждать завершения надо в run() второго потока. Но это странно.


второго - это какого ? и чем странно то...

Цитата(SABROG @ 24.6.2009, 17:29) *
А для чего такие сложности со вторым останавливающим потоком?

просто операция остановки довольно длительная и поэтому приходится выводить диалог ожидания, который рисуется только в главном окне и ждет завершения потока
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

2 страниц V   1 2 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 22.12.2024, 13:45