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

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

Страниц: 1 [2] 3 4   Вниз
  Печать  
Автор Тема: Процесс замерзает при работе интерфейса  (Прочитано 23020 раз)
vulko
Гость
« Ответ #15 : Ноябрь 14, 2014, 09:32 »

Цитировать
само собой, но речь не об этом, а о том, что при разных последовательных запусках одного и того же QThread::run() получаются разные нити, которые не могут работать с одним и тем же мутексом, также как если бы это была одна и та же нить - а проблема у меня именно в этом

Что за последовательные запуски одного и того же QThread::run? Это как?
Ты создаешь разные объекты QThread и делаешь им start()?

Разные нити могут работать с одним и тем же мьютексом, но мьютекс должен быть обязательно один. Т.е. создаваться не в потоке, но у потоков ссылка на него должна быть.
Если мьютекс у них будет один, то они будут работать последовательно.

Зачем последовательно запускаешься QThread::run?

Может лучше сделать?

Код:
run() {
    while(running) {
        // do stuff or just wait for signal
        exec();
    }
}
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #16 : Ноябрь 14, 2014, 12:31 »

Что за последовательные запуски одного и того же QThread::run? Это как?
Ты создаешь разные объекты QThread и делаешь им start()?

нет, разумеется... во-первых, не start(), а run(), во-вторых один объект QThread один раз создан, когда надо он запускается, выполняет действия, останавливается, потом когда снова надо снова запускается и т.д. - такова логика задачи, и это изменить нельзя

за все остальные банальности спасибо, но всё это мне давным давно известно, и ничего для решения проблемы не даёт
Записан

2^7-1 == 127, задумайтесь...
vulko
Гость
« Ответ #17 : Ноябрь 14, 2014, 12:57 »

Что за последовательные запуски одного и того же QThread::run? Это как?
Ты создаешь разные объекты QThread и делаешь им start()?

нет, разумеется... во-первых, не start(), а run(), во-вторых один объект QThread один раз создан, когда надо он запускается, выполняет действия, останавливается, потом когда снова надо снова запускается и т.д. - такова логика задачи, и это изменить нельзя

за все остальные банальности спасибо, но всё это мне давным давно известно, и ничего для решения проблемы не даёт

если ты дергаешь run(), то он выполняется в том же потоке.
а если start(), то он создает поток и в нем выполняет run().

логика абсолютно нормальная. криво реализовано просто.

если все известно, не вижу причин чтобы приложение не работало.
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #18 : Ноябрь 14, 2014, 13:25 »

если все известно, не вижу причин чтобы приложение не работало.

приложение работает, но неожиданностью было то, что при последовательных запусках (разумеется, снаружи запуск вызовом start()) одного и того же QThread на самом деле получаются разные нити, в документации этого нет

проблема в том, что разные участники процесса находятся в разных плагинах, взаимодействие между которыми не так легко осуществлять - обмен обычными данными нормально по сигнал-слотам производится, но вот управление потоками уже не так просто
Записан

2^7-1 == 127, задумайтесь...
vulko
Гость
« Ответ #19 : Ноябрь 14, 2014, 14:49 »

если все известно, не вижу причин чтобы приложение не работало.

приложение работает, но неожиданностью было то, что при последовательных запусках (разумеется, снаружи запуск вызовом start()) одного и того же QThread на самом деле получаются разные нити, в документации этого нет

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

если делаешь stop start, то это нормально.
а вообще не очень понимаю что значит последовательный запуск одного и того же qthread... несколько раз дергаешь start?


советую вот такое попробовать:

Код:
void MyThread::run() {
    // init
    mContinue = new QMutex;
    mWaitCondition = new QWaitCondition;

    while(running) {
        lock();
        // do stuff
        unlock();

        if (pause) {
            mWaitCondition->wait(mContinue);
        }

        exec();
    }
}

void MyThread::pause() { pause = true; }

void MyThread::resume() {
    if (pause) {
        pause = false;
        mWaitCondition->wakeAll();
    }
}

Так сам сможешь контролировать когда приостановить поток, когда продолжить работу. Причем без сигналов, соотв. быстрее.
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #20 : Ноябрь 14, 2014, 15:30 »

Код:
[quote author=vulko link=topic=27922.msg203570#msg203570 date=1415965762]
а вообще не очень понимаю что значит последовательный запуск одного и того же qthread... несколько раз дергаешь start?

Типа того, только не я дергаю - пользователь. Объект QThread создается один раз при старте задачи и связывается с загруженными плагинами. Создавать его каждый раз заново нельзя - это поломает всю структуру и весь отлаженный код, которого море. Когда пользователю надо, он нажимает кнопочку и выполняется соответствующий QThread::start(). Более того, таких нитей может и должно быть несколько, причем пользователь может запускать их произвольно. И они общаются друг с другом через сигнал-слоты, которые пользователь может связывать вручную. По другому никак нельзя. Таково условие задачи ака ТЗ.

советую вот такое попробовать:

Код:
void MyThread::run() {
    // init
    mContinue = new QMutex;

Это невозможно. MyThread не имеет права ничего знать про мутексы где-то там внутри. Он лишь выполняет код загруженного плагина. Плагин может иметь мутексы, может не иметь.
Записан

2^7-1 == 127, задумайтесь...
vulko
Гость
« Ответ #21 : Ноябрь 14, 2014, 18:12 »

Это невозможно. MyThread не имеет права ничего знать про мутексы где-то там внутри. Он лишь выполняет код загруженного плагина. Плагин может иметь мутексы, может не иметь.

омг...
в каком нутри?

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

речь идет о синхронизации основного потока с потоками в которых запускаются плагины, а не синхронизации плагинов с потоками.


Типа того, только не я дергаю - пользователь. Объект QThread создается один раз при старте задачи и связывается с загруженными плагинами. Создавать его каждый раз заново нельзя - это поломает всю структуру и весь отлаженный код, которого море. Когда пользователю надо, он нажимает кнопочку и выполняется соответствующий QThread::start(). Более того, таких нитей может и должно быть несколько, причем пользователь может запускать их произвольно. И они общаются друг с другом через сигнал-слоты, которые пользователь может связывать вручную. По другому никак нельзя. Таково условие задачи ака ТЗ.

вернемся к началу.
плагины-шмагины. все это никакого отношения не имеет к вопросу. более того, если как ты говорил, плагина может не быть, то вообще ничего делать в run() не надо. т.е. неплохо бы проверить если он вообще для начала.

а вопрос твой изначально был таким:
Код:
Если в QThread запустилась нитка, залочила некий мутекс, завершилась (но мутекс не разлочился), и потом снова запустилась (тот же объект QThread) - при повторном запуске, вместо dead-lock она в этом мутексе просто молча залипает.

если поток завершил работу, но не разлочил мьютекс, значит это кривой поток. или кривой программист.
для таких случаев есть крит секция. вот её и используй!

молча залипает, потому что, как уже говорили тебе выше, мьютекс лочится дважды из одного и того же потока. т.е. лочится сам на себе. это почти dead lock, только в рамках одного потока, а не взаимная блокировка потоков.
Записан
Bepec
Гость
« Ответ #22 : Ноябрь 14, 2014, 19:49 »

Тут явная хрень в архитектуре.
Нитка блочащая мутекс не создаёт мутекс. Мутекс имеется в dll, а может и не иметься. Это сюрреалистический бред архитектуры.

Соберитесь. Разложите задачу на составные части. И не позволяйте сущностям убегать из своей части. Нитка лочащая  мутекс должна его разлочивать Точка
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #23 : Ноябрь 14, 2014, 20:37 »

Тут явная хрень в архитектуре.
Нитка блочащая мутекс не создаёт мутекс. Мутекс имеется в dll, а может и не иметься. Это сюрреалистический бред архитектуры.

Соберитесь. Разложите задачу на составные части. И не позволяйте сущностям убегать из своей части. Нитка лочащая  мутекс должна его разлочивать Точка

Я НЕ ПОЗВОЛЯЮ УБЕГАТЬ СУЩНОСТЯМ! Мутекс может иметься в DLL, а может и не иметься. И в одной задаче могут быть плагины как с мутексами, так и без мутексов. И даже плагин могу не я написать, а кто-то другой лет через пять. То есть, лочиться и разлочиться мутекс должен только внутри плагина, и больше нигде. Никакого бреда тут нет.

Сюрреализм есть, но он в том, что один QThread при разных запусках имеет разный ThreadID. Это потому, что start() запускает каждый раз новую нить на системном уровне. Я бы сделал так, чтобы в конструкторе самого QThread создавалась и запускалась на время существования этого объекта только одна нить, но чтобы в самом конструкторе она ставилась в ожидание, а start() просто разрешал ей работать, вызывая run(). Тогда у всех последовательных запусков был бы один тот же ThreadID, и мутексы, залоченные при одном запуске, можно было бы разлочить при следующем запуске. То есть - один QThread == один и тот же процесс. Всегда, пока этот QThread существует. Увы, но в Qt это совсем не так. Это и есть сюрреализм.

С утра, проспавшись, вдруг подумал, а почему не сделать так в процедуре, которая ожидает прихода сигналов (сигналы принимаются основным потоком, как написано в начале):

Код:
        _waiterLockMutex();         //     waiterMutex.lock();
        _waiterLocker();            //     waiterWaitCondition.wait( &waiterMutex );
        _waiterUnLockMutex();       //     waiterMutex.unlock();

в приемнике сигнала просто
Код:
        waiterWaitCondition.wakeOne();

Сделал. Вроде работает всё...
« Последнее редактирование: Ноябрь 14, 2014, 22:03 от Гурман » Записан

2^7-1 == 127, задумайтесь...
vulko
Гость
« Ответ #24 : Ноябрь 14, 2014, 20:43 »

О чем вообще речь? Вы хоть знаете что такое мьютекс и как он работает?
Вы знаете что залочив разные мьютексы из одного потока ничего не случиться?

Причем тут вообще внутренности плагина и его мьютексы? Это все остается внутри!
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #25 : Ноябрь 14, 2014, 20:54 »

Вы хоть знаете что такое мьютекс и как он работает?

знаю, где-то с начала 90-х... в конце 90-х в реализации семафоров BeOS ошибку нашел

у меня проблема была не в мутексах, читайте внимательнее
« Последнее редактирование: Ноябрь 14, 2014, 21:30 от Гурман » Записан

2^7-1 == 127, задумайтесь...
vulko
Гость
« Ответ #26 : Ноябрь 14, 2014, 21:34 »

Вы хоть знаете что такое мьютекс и как он работает?

знаю, где-то с начала 90-х... в конце 90-х в реализации семафоров BeOS ошибку нашел

у меня проблема была не в мутексах, читайте внимательнее


может стоит изъясняться понятным образом?
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #27 : Ноябрь 14, 2014, 22:04 »

может стоит изъясняться понятным образом?

у понятности изложения всегда есть две стороны...
Записан

2^7-1 == 127, задумайтесь...
Bepec
Гость
« Ответ #28 : Ноябрь 14, 2014, 22:12 »

Я тоже не могу уловить ваши рассуждения. У вас проблема с Mutex. Выше вы говорили что лочится он в потоке, А разлочивается хз где. И дальше говорите что его вообще может не быть.

Как может существовать поток с мутексом без мутекса? бред.
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #29 : Ноябрь 14, 2014, 22:20 »

Я тоже не могу уловить ваши рассуждения. У вас проблема с Mutex. Выше вы говорили что лочится он в потоке, А разлочивается хз где. И дальше говорите что его вообще может не быть.

Как может существовать поток с мутексом без мутекса? бред.

Проблема была не с мутексом. Проблема с разными нитями запускаемыми одним и тем же QThread. Поскольку после запуска, завершения и снова запуска нити разные

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

в разных случаях, в зависимости от конфигурации, один и тот QThread может обслуживать разные плагины - в одних есть необходимость синхронизации, в других нет - теперь понятно?
Записан

2^7-1 == 127, задумайтесь...
Страниц: 1 [2] 3 4   Вверх
  Печать  
 
Перейти в:  


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