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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Потоки и QList  (Прочитано 8141 раз)
a1ien
Гость
« : Декабрь 01, 2011, 14:12 »

Помогите пожалуйста понять что я не так делаю. В архиве проект который падает при нажатии на кнопку.
Как я понял приложение падает когда из QList создается копия хранящейся в нем структуры.
Проблема в файле Sender.cpp в функции run()

PS Это выделенный участок проблемного кода из другого проекта.
Записан
Bepec
Гость
« Ответ #1 : Декабрь 01, 2011, 14:39 »

Ну насколько я понял, у тебя поток обращается еще к пустому элементу листа Улыбающийся. Соответственно рушит память и программу.

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

И кстати, если цикл в run будет пустым (пара десятков строк не считается), то тогда он будет еще и грузить машину оч сильно Улыбающийся
Записан
a1ien
Гость
« Ответ #2 : Декабрь 01, 2011, 15:04 »

Да забыл добавить из основного проекта проверку на пустой список.
Код
C++ (Qt)
void QSender::run()
{
   while(1)
   {
       if(!mainTable->ARP_cash.isEmpty())
       {
           //        QList<TableModel::ARP>::const_iterator i;
           //        for (i = mainTable->ARP_cash.constBegin(); i != mainTable->ARP_cash.constEnd(); ++i)
           //        {
           //            if(((TableModel::ARP)*i).widget->isStarted())
           //            {
           //                //arp.widget->isUDP()?SendUdpECHO(arp):SendECHO(arp);
           //                msleep(5);
           //            }
           //        }
           foreach(TableModel::ARP arp,mainTable->ARP_cash)
           {
               //            if(arp.widget->isStarted())
               //            {
               //                //arp.widget->isUDP()?SendUdpECHO(arp):SendECHO(arp);
               //                msleep(5);
               //            }
           }
       }
   }
 
}
Что должен делать поток. Пробегает по списку найденных устройств и у элементов у которых нажата кнопку делает отправку(она щас закоментирована).
Да и на нагрузку наплевать. Там будут задержки через sleep или наоборот надо будет отправлять как можно быстрее.
« Последнее редактирование: Декабрь 01, 2011, 15:13 от a1ien » Записан
Bepec
Гость
« Ответ #3 : Декабрь 02, 2011, 06:55 »

Таки с проверкой не падает? или продолжает?

Если поток в цикле будет спать или работать, то это нормально Улыбающийся а если пустой цикл это плохо.
Записан
Aluman
Гость
« Ответ #4 : Декабрь 02, 2011, 08:40 »

Судя по всему из разных потоков происходит обращение к одним и тем же данным, если в методе void MainWindow::on_pushButton_clicked(), перенести добавление новых записей до запуска потока, то все заработает:

Было:
Код:
    if(!sender->isRunning())
        sender->start();
    mainTable->AddRecord("192.168.0.1",QString("001A9236F347").toAscii());
    mainTable->AddRecord("192.168.0.2",QString("001A9236F357").toAscii());
    mainTable->AddRecord("192.168.0.3",QString("001A9236F367").toAscii());
    mainTable->AddRecord("192.168.0.4",QString("001A9236F387").toAscii());

Стало:
Код:
    mainTable->AddRecord("192.168.0.1",QString("001A9236F347").toAscii());
    mainTable->AddRecord("192.168.0.2",QString("001A9236F357").toAscii());
    mainTable->AddRecord("192.168.0.3",QString("001A9236F367").toAscii());
    mainTable->AddRecord("192.168.0.4",QString("001A9236F387").toAscii());
    if(!sender->isRunning())
        sender->start();
« Последнее редактирование: Декабрь 02, 2011, 08:42 от Aluman » Записан
Bepec
Гость
« Ответ #5 : Декабрь 02, 2011, 08:53 »

Скажу просто - это обычная ситуация с мутексом. Он там стоит, где надо. Поток при натыкании на закрытый мутекс должен дождаться его разблокировки.
Скорее у вас непонятная архитектура. Я просто не могу понять что вы делаете Улыбающийся
Записан
Aluman
Гость
« Ответ #6 : Декабрь 02, 2011, 09:00 »

Скажу просто - это обычная ситуация с мутексом. Он там стоит, где надо. Поток при натыкании на закрытый мутекс должен дождаться его разблокировки.
Скорее у вас непонятная архитектура. Я просто не могу понять что вы делаете Улыбающийся
В потоке не используются никакие мьютексы, он ничего не ждет.
Записан
Bepec
Гость
« Ответ #7 : Декабрь 02, 2011, 09:05 »

отпишу попозже есть мысль, место поста не занимать, это не оффтоп.
Записан
a1ien
Гость
« Ответ #8 : Декабрь 02, 2011, 11:13 »

Хорошо делаем так.
Код
C++ (Qt)
mainTable->AddRecord("192.168.0.1",QString("001A9236F347").toAscii());
   mainTable->AddRecord("192.168.0.2",QString("001A9236F357").toAscii());
   mainTable->AddRecord("192.168.0.3",QString("001A9236F367").toAscii());
   mainTable->AddRecord("192.168.0.4",QString("001A9236F387").toAscii());
   if(!sender->isRunning())
       sender->start();
   mainTable->AddRecord("192.168.0.5",QString("001A9236F348").toAscii());
   mainTable->AddRecord("192.168.0.6",QString("001A9236F359").toAscii());
   mainTable->AddRecord("192.168.0.7",QString("001A9236F360").toAscii());
   mainTable->AddRecord("192.168.0.8",QString("001A9236F381").toAscii());
 
Он будет тоже падать.
Вобщем что мне надо. Мне надо чтобы поток стартовал тогда когда начинается заполнятся mainTable->ARP_cash этьо раз
Второе Поток делает вот что. Он смотрит у каких виджетов списке нажата кнопка старт. У тех которых нажата он запускает отправку.

Я тоже вполне допускаю, что  гдето в run или еще гдето нужен мютекс но как бы я туда его не ставил все равно падает.
Щас мютекс стоит в mainTable->AddRecord
Записан
Aluman
Гость
« Ответ #9 : Декабрь 02, 2011, 16:48 »

Код:
class TableModel
{
...
private:
  QMutex mutex;
...
}

void TableModel::AddRecord(QString IPaddress, QByteArray MACaddress)
{
    QMutexLocker locker(&mutex);
    ...

}

void TableModel::SomeFunction()
{
    QMutexLocker locker(&mutex);
    ...
    foreach(TableModel::ARP arp,mainTable->ARP_cash)
    {
       ...
    }
    ...
}

void QSender::run()
{
    ....
   mainTable->SomeFunction();
    ....
}

  Как-то так поидеи должно работать, только при выполнении метода AddRecord gui поток может подвисать ожидая освобождения мьютекса.
Записан
qt_user
Гость
« Ответ #10 : Декабрь 02, 2011, 22:30 »

ТС
используйте семафоры и не изобретайте велосипеды, если не знает про что я вообще говорю почитайте что
такое семафор и посмотрите в ассистанте "Semaphores Example" ваше задача - классика "producer-consumer"
Записан
Bepec
Гость
« Ответ #11 : Декабрь 05, 2011, 07:04 »

qt_user - не отвечайте общими фразами, а приведите пример на данном проекте Улыбающийся
Записан
andrew.k
Гость
« Ответ #12 : Декабрь 05, 2011, 08:23 »

qt_user - не отвечайте общими фразами, а приведите пример на данном проекте Улыбающийся
Ахахахаха. Весьма странно слышать это от тебя)

У тебя там мысль была, она загнулась или еще не вылезла до конца?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Декабрь 05, 2011, 11:45 »

Щас мютекс стоит в mainTable->AddRecord
Так ведь он там же и объявлен - ну и никого не защищает. Надо использовать один и тот же мутекс в AddRecord и в run нитки

Вобщем что мне надо. Мне надо чтобы поток стартовал тогда когда начинается заполнятся mainTable->ARP_cash этьо раз
Не надо всякий раз стартовать нитку, это плохо. Напр она могла еще быть занята предыдущей обработкой. Просто "будите" ее напр семафором

Код
C++ (Qt)
void Sender::run( void )
{
 while (true) {
  theSemaphore.acquire();
  if (mStopFlag) break;
  QMutexLocker(&theMutex);
  // тут крутите foreach и всю любовь
 }
}
 

A добавление так
Код
C++ (Qt)
QMutexLocker(&theMutex);  // ждем пока Sender не освободит
mainTable->AddRecord("192.168.0.1",QString("001A9236F347").toAscii());
...
theSemaphore.release();   // будим Sender'а
 
« Последнее редактирование: Декабрь 05, 2011, 11:47 от Igors » Записан
Aluman
Гость
« Ответ #14 : Декабрь 05, 2011, 13:28 »

Что-то я не совсем понимаю Непонимающий  Пример "Semaphores Example" хороший, но человеку судя по всему нужно не совсем это. Просто один поток непрерывно просматривает список и делает какие-то действия. Второй поток пытается в этот список что-то добавить/удалить - один мьютекс для запрета обращения к одному с списку из разных потоков. Чем мое решение людям не понравилось, вроде все просто и понятно? Да и a1ien видать решил как-то проблему и молчит как партизан  Веселый
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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