Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: a1ien от Декабрь 01, 2011, 14:12



Название: Потоки и QList
Отправлено: a1ien от Декабрь 01, 2011, 14:12
Помогите пожалуйста понять что я не так делаю. В архиве проект который падает при нажатии на кнопку.
Как я понял приложение падает когда из QList создается копия хранящейся в нем структуры.
Проблема в файле Sender.cpp в функции run()

PS Это выделенный участок проблемного кода из другого проекта.


Название: Re: Потоки и QList
Отправлено: Bepec от Декабрь 01, 2011, 14:39
Ну насколько я понял, у тебя поток обращается еще к пустому элементу листа :). Соответственно рушит память и программу.

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

И кстати, если цикл в run будет пустым (пара десятков строк не считается), то тогда он будет еще и грузить машину оч сильно :)


Название: Re: Потоки и QList
Отправлено: a1ien от Декабрь 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 или наоборот надо будет отправлять как можно быстрее.


Название: Re: Потоки и QList
Отправлено: Bepec от Декабрь 02, 2011, 06:55
Таки с проверкой не падает? или продолжает?

Если поток в цикле будет спать или работать, то это нормально :) а если пустой цикл это плохо.


Название: Re: Потоки и QList
Отправлено: Aluman от Декабрь 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();


Название: Re: Потоки и QList
Отправлено: Bepec от Декабрь 02, 2011, 08:53
Скажу просто - это обычная ситуация с мутексом. Он там стоит, где надо. Поток при натыкании на закрытый мутекс должен дождаться его разблокировки.
Скорее у вас непонятная архитектура. Я просто не могу понять что вы делаете :)


Название: Re: Потоки и QList
Отправлено: Aluman от Декабрь 02, 2011, 09:00
Скажу просто - это обычная ситуация с мутексом. Он там стоит, где надо. Поток при натыкании на закрытый мутекс должен дождаться его разблокировки.
Скорее у вас непонятная архитектура. Я просто не могу понять что вы делаете :)
В потоке не используются никакие мьютексы, он ничего не ждет.


Название: Re: Потоки и QList
Отправлено: Bepec от Декабрь 02, 2011, 09:05
отпишу попозже есть мысль, место поста не занимать, это не оффтоп.


Название: Re: Потоки и QList
Отправлено: a1ien от Декабрь 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


Название: Re: Потоки и QList
Отправлено: Aluman от Декабрь 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 поток может подвисать ожидая освобождения мьютекса.


Название: Re: Потоки и QList
Отправлено: qt_user от Декабрь 02, 2011, 22:30
ТС
используйте семафоры и не изобретайте велосипеды, если не знает про что я вообще говорю почитайте что
такое семафор и посмотрите в ассистанте "Semaphores Example" ваше задача - классика "producer-consumer"


Название: Re: Потоки и QList
Отправлено: Bepec от Декабрь 05, 2011, 07:04
qt_user - не отвечайте общими фразами, а приведите пример на данном проекте :)


Название: Re: Потоки и QList
Отправлено: andrew.k от Декабрь 05, 2011, 08:23
qt_user - не отвечайте общими фразами, а приведите пример на данном проекте :)
Ахахахаха. Весьма странно слышать это от тебя)

У тебя там мысль была, она загнулась или еще не вылезла до конца?


Название: Re: Потоки и QList
Отправлено: Igors от Декабрь 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'а
 


Название: Re: Потоки и QList
Отправлено: Aluman от Декабрь 05, 2011, 13:28
Что-то я не совсем понимаю ???  Пример "Semaphores Example" хороший, но человеку судя по всему нужно не совсем это. Просто один поток непрерывно просматривает список и делает какие-то действия. Второй поток пытается в этот список что-то добавить/удалить - один мьютекс для запрета обращения к одному с списку из разных потоков. Чем мое решение людям не понравилось, вроде все просто и понятно? Да и a1ien видать решил как-то проблему и молчит как партизан  :D


Название: Re: Потоки и QList
Отправлено: andrew.k от Декабрь 05, 2011, 13:31
Он почитал советы Вереса и сошел с ума)
Ждем выздоровления.


Название: Re: Потоки и QList
Отправлено: Igors от Декабрь 05, 2011, 14:07
Чем мое решение людям не понравилось, вроде все просто и понятно?
Уже и "решение" :) A в предыдущем Вашем посте это выглядело как набросок
Код:
void QSender::run()
{
    ....
   mainTable->SomeFunction();
    ....
}
 Как-то так поидеи должно работать, только при выполнении метода AddRecord gui поток может подвисать ожидая освобождения мьютекса.
Ах как приятно мыслить как художник: "как-то так" (мол, образ), "по идее" (2 ошибки не имеют значения) и.т.п.  :)

Но вот мне (тупенькому технарю) неясно что в run делать? Если вместо точек - ничего, то он сразу и выйдет. А если просто зациклить, то он весь процессор выжрет, молотьба по пустому. Поэтому нужен семафор чтобы он делал когда есть работа для него.


Название: Re: Потоки и QList
Отправлено: a1ien от Декабрь 05, 2011, 16:44
Совет Aluman помог. Я вобщем понял свою ошибку всем спс за совету)