Pull to refresh
2
0
Алексей @GAlex1980

DevOps, программист, пентестер

Send message

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

Чего только люди не придумают, лишь бы не объявлять переменные флагов и другие общие объекты как volatile.

Вы хоть читали документацию?

Enters the event loop and waits until exit() is called, returning the value that was passed to exit().

exec() это цикл обработки событий! На нем все будет виснуть, т.к. он обрабатывать только очередь событий. Ваш случай - мой вариант waitForEndThread() или изменение архитектуры приложения так, чтобы в quit() или wait() не было необходимости.

PS. Если это какой-то коммерческий/полукоммерческий проект - наймите фрилансера с необходимыми скиллами.

Дабы не плодить на техническом ресурсе бесполезную лирику, предлагаю проанализировать то, что написано в книге Боровский и у вас. Тем более у меня нет русской раскладки, чтобы быстро отвечать вам.
У Боровский в методе run() выполняется:

  • создание локальной переменной, ее инициализация (параметры, связывание через connect())

  • запуск

  • вызов exec()

In the Qt Documentation:
int QThread::exec()
Enters the event loop and waits until exit() is called, returning the value that was passed to exit(). The value returned is 0 if exit() is called via quit().
This function is meant to be called from within run(). It is necessary to call this function to start event handling.
Note: This can only be called within the thread itself, i.e. when it is the current thread.

О, есть цикл обработки событий внутри дочернего потока.
Идем далее.
У меня нет полных исходников примера из Боровский, но переменная thread объявлена в классе главного окна. Ее срок жизни - срок жизни приложения, т.е. главного потока.
Смотрим, что будет при завершении приложения.
Смотрим деструктор:

  • проверка того, что thread != nullptr

  • вызов quit()

  • вызов wait() //с дефолтными параметрами

In the Qt Documentation:
void QThread::quit()
Tells the thread's event loop to exit with return code 0 (success). Equivalent to calling QThread::exit(0).
This function does nothing if the thread does not have an event loop.
Note: This function is thread-safe.

bool QThread::wait(QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever))
Blocks the thread until either of these conditions is met:
The thread associated with this QThread object has finished execution (i.e. when it returns from run()). This function will return true if the thread has finished. It also returns true if the thread has not been started yet.
The deadline is reached. This function will return false if the deadline is reached.
A deadline timer set to QDeadlineTimer::Forever (the default) will never time out: in this case, the function only returns when the thread returns from run() or if the thread has not yet started.
This provides similar functionality to the POSIX pthread_join() function.

Ага, есть метод отправки сигнала (QThread::quit()) на завершение выполнения дочернего потока, которую примет цикл обработки событий (QThread::exec()).
После получения сигнала на завершение, будет выход из метода run(), который по сути означает завершение выполнения потока и освобождение ресурсов.

Мы ждем корректного завершения потока (QThread::wait()) и освобождения связанных с ним ресурсов во избежание их утечки. Так как в примере в потоке ничего особенного не выполняется, то задержка на wait() будет мизерной.

Код примера из Боровский полностью корректный для использования в той ситуации.

Теперь смотрим на ваш код (Листинг 1).
Внутри метода run() есть цикл обработки данных и нет цикла обработки событий.
Внутри FThCounter::~FThCounter() и FThCounter::WaitForThreadToFinish():

  • вызов quit()

  • вызов wait() //с дефолтными параметрами

Касательно разницы в работе. Надо смотреть под отладчиком, что именно возвращает QThread::currentThread() и есть ли потоки с таким ID (см справку).

Метод quit() отправляет команду на завершение выполнения дочернего потока. Вот только чем и где он будет принят - я сказать не могу. У меня только одна ассоциация: "Uciekł gdzie pieprz rośnie" (в неизвестном направлении). Нужно смотреть исходники QThread, но ваш код - потенциальный UB.
Метод wait() - может ждать бесконечно долго или сразу возвратить true, в зависимости от состояния экземпляра класса FThCounter.

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

Мне хотелось бы знать, как быстро "убить" поток. Но как?

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

Это просто абстрактный пример класса, который реализует поток. Хотя, примеры взяты из кода моих проектов.

В деструкторе ThreadWorker::~ThreadWorker() удалять динамически созданные члены класса, закрыть используемые ресурсы и т.д.

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

Если вы хотите запустить дочерний поток из основного потока (или еще откуда-то) и дождаться окончания выполнения (естественного или по соотв.сигналу), то вам нужно действовать примерно так:

ThreadWorker worker; // либо через оператор new
worket.init(setup_params); //необязательное. setup_params набор параметров, которые надо отдать в поток
worket.start(); //начинается выполнение содердимого переопределенного метода run()
worker.waitForEndThread(100); //мой метод, описанный выше
//... other code

В строке 4 внутри метода каждые 100 мс wait() будет сбрасываться в true и будет обрабатываться очередь сообщений (сигналы слотам). Потом в цикле все будет повторяться, пока не будет выполнен выход из метода run().

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

Вообще, потоки - специфическая вещь и для каждой конкретной задачи нужна своя реализация.

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

wait(); // неограниченное ожидание завершения потока

Результатом может быть "замораживание" графического интерфейса (если он будет использоваться), очереди событий и т.д. Думаю, лучше использовать подобный код:

void waitForEndThread(QThread *obj, unsigned long time)
{
    while (!obj->wait(time)) {
        QCoreApplication::processEvents();
    }
}

Возможно, реализуется перехват методом ван Эйка. Первоначально он был реализован для ЭЛТ-мониторов, но потом эго адаптировали и для ЖК.

Но, там расстояние - десятки метров.

Странно, что не упомянули Iridium. А ведь с такой помпой открывали наземную станцию сопряжения в Ижевске...

У вас в форме предлагается ввести корпоративную почту. Т.е., по сути, отсекаются те, кто хочет поучаствовать в тестировании в частном порядке.

Доброе время суток! Когда планируется реализовать поддержку Qt Creator 10.x?

Доброй ночи. В этой проблеме виноват я. Я все пути в аргументах команды CompilerCommandsAnalyzer (путь к лицензии, логфайлу, исключаемые пути) экранировал при помощи одинарных ковычек. Заменил их на двойные и программа успешно прочитала файл лицензий.

Приношу извинения за ложную информацию.

Решил ради праздного любопытства попробовать PVS-Studio в Qt. Но, CompilerCommandsAnalyzer.exe не воспринимает "PVS-Studio Free" лицензию. А так, в целом, интеграция с Qt это прекрасно.

Добрый день. Какой брандмауэр используется?

Добрый вечер. Можете поделиться информацией, куда стучится Nextcloud и что Вы ему перекрыли?

Как по мне, основные причины:

  • все технологии разрабатывались только для ВПК. Грифы секретности не позволяли их в должной мере применять в гражданских сферах. В итоге, большая часть разработанных технологий не приносила прибыли.

  • генетика и кибернетика - лженауки. В итоге СССР практически проиграла в гонке микропроцессорной техники.

У меня было подобное. Помогло обращение в сапорт.
Метилметакрилат внесен в Перечень наркотических средств, психотропных веществ и их прекурсоров, подлежащих контролю в РФ.
И давить ошибки разработчикам сайта наверное религия мешала :)
1

Information

Rating
3,878-th
Location
Bełk, Katowice, Польша
Registered
Activity