Название: потоки Отправлено: CPP11 от Декабрь 07, 2014, 23:24 Доброго времени суток. В ближайшее время нужно будет написать многопоточное приложение на QT, поэтому прошу прояснить некоторые моменты...
Суть приложения - есть 2 потока - Gui и General. Gui - отвечает за пользовательский интерфейс и принимает от системы сообщения о подключаемом оборудовании(WM_DEVICECHANGE, только windows). General - обрабатывает команды от Gui и сигнализирует в ответ об изменениях, которые нужно отобразить, обрабатывать может очень долго, потому и выделен в отдельный поток. Насколько я понял второй поток нужно создавать как в этой заметке (http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/): Код: //worker.h Название: Re: потоки Отправлено: Johnik от Декабрь 08, 2014, 00:44 и пока я не уничтожу объект worker поток не завершится и будет обрабатывать сигналы. нет, поток не завершится, пока вы его не остановите: quit() или terminate().И в этой конструкции, если поток Gui отправит последовательно два сигнала, то я могу быть уверен, что другой поток обработает эти сигналы именно в этой последовательности и дополнительной синхронизации не нужно. Это верно? да, верно.Название: Re: потоки Отправлено: Igors от Декабрь 08, 2014, 12:17 если поток Gui отправит последовательно два сигнала, то я могу быть уверен, что другой поток обработает эти сигналы именно в этой последовательности и дополнительной синхронизации не нужно. Это верно? Для только одного "отправляющего" - верно, для 2 и более - нет Название: Re: потоки Отправлено: Old от Декабрь 08, 2014, 12:19 если поток Gui отправит последовательно два сигнала, то я могу быть уверен, что другой поток обработает эти сигналы именно в этой последовательности и дополнительной синхронизации не нужно. Это верно? Для только одного "отправляющего" - верно, для 2 и более - нет Название: Re: потоки Отправлено: Igors от Декабрь 08, 2014, 12:54 Два Gui потока в Qt? Это фантастика. "Напрасно, все меняется очень быстро" :) C 2 и более - один их самых "кровавых" багов с которыми я имел делоНазвание: Re: потоки Отправлено: Old от Декабрь 08, 2014, 13:15 C 2 и более - один их самых "кровавых" багов с которыми я имел дело Что вы называете "кровавым" багом?То что если два потока добавляют сообщения в одну очередь сообщения могут чередоваться? Название: Re: потоки Отправлено: Igors от Декабрь 08, 2014, 13:33 То что если два потока добавляют сообщения в одну очередь сообщения могут чередоваться? Да. Псевдокод (если не ошибаюсь, в 3-й раз)Цитировать SendEvent(receiver, jobAbort, ...); Это не вызывает сомнений, действительно resetStatus выполнится после jobAbort. Но это совсем не значит что resetStatus будет обрабатываться сразу после jobAbort (хотя мы их и посылали немедленно одно за другим). При 2 и более отправителях др события могут вклиниться в очередь между нашими 2-мя.. изменить контекст получателя и тогда..SendEvent(receiver, resetStatus, ...); Конечно, это "совсем очевидно" :) Название: Re: потоки Отправлено: Old от Декабрь 08, 2014, 13:40 Конечно, это "совсем очевидно" :) Ну, как бы, да. :)Очереди сообщений это все те же очереди данных. Название: Re: потоки Отправлено: Johnik от Декабрь 08, 2014, 13:42 Для только одного "отправляющего" - верно, для 2 и более - нет пример приведите, где не вернопо моему опыту и более 10 потоков работало Название: Re: потоки Отправлено: Igors от Декабрь 08, 2014, 13:48 пример приведите, где не верно И по моему тоже. Просто раз в месяц пользователь сообщал о каком-то вылете. Ну добавил логи, потом еще их расширил - возился долго. Обратите внимание на "именно в этой последовательности". Так вот, при 2 и более отправителях последовательность НЕ "именно та".по моему опыту и более 10 потоков работало Название: Re: потоки Отправлено: CPP11 от Декабрь 08, 2014, 19:05 нет, поток не завершится, пока вы его не остановите: quit() или terminate(). Значит для корректного завершения потока нужно выполнить примерно такой код:Код: thread->quit(); Название: Re: потоки Отправлено: Igors от Декабрь 08, 2014, 19:14 Без всяких 1000 - просто thread->wait()
Название: Re: потоки Отправлено: CPP11 от Декабрь 08, 2014, 19:29 Без всяких 1000 - просто thread->wait() нет, ну 50 дней его ждать точно не нужно, если за секунду не умер, то пусть аварийно завершается :) .Название: Re: потоки Отправлено: Johnik от Декабрь 08, 2014, 19:30 Так вот, при 2 и более отправителях последовательность НЕ "именно та". "кто успел тот и съел"Название: Re: потоки Отправлено: Igors от Декабрь 08, 2014, 19:45 нет, ну 50 дней его ждать точно не нужно, если за секунду не умер, то пусть аварийно завершается :) . Давайте без самодеятельности, аварийное завершение - себе дороже. Единственный способ завершить thread - дать ей нормально выйти. Никуда не денется - выйдет, не надо дергатьсяНазвание: Re: потоки Отправлено: CPP11 от Декабрь 08, 2014, 20:05 Давайте без самодеятельности, аварийное завершение - себе дороже. Единственный способ завершить thread - дать ей нормально выйти. Никуда не денется - выйдет, не надо дергаться Это ошибочный подход, лучше завершить/перезапустить зависшее приложение, чем оставлять его на самотёк. Это негативно сказывается на юзабилити и усложняет сбор сведений о сбоях для дальнейшего анализа.Название: Re: потоки Отправлено: Alexu007 от Декабрь 09, 2014, 00:29 Так вот, при 2 и более отправителях последовательность НЕ "именно та". "кто успел тот и съел"Название: Re: потоки Отправлено: Johnik от Декабрь 09, 2014, 00:57 От решаемой задачи зависит. Почему бы в сообщения не вставить порядковые номера, а получатель пусть решает, как поступать с сообщениями - сразу обрабатывать или сбросить в буфер и пусть ждёт очереди? Но если будет много инфы в очереди - то может здесь вообще потоки лучше не использовать? Сложный алгоритм работы с очередью сообщений съест эффект быстродействия потоков. О каких сообщениях и очередях идет речь? CPP11 в начале говорил об механизме сигналов/слотов. Сигналы попадают в очередь сообщений Qt, и именно Qt распределяет их по потокам.Название: Re: потоки Отправлено: Igors от Декабрь 09, 2014, 14:45 Это ошибочный подход, лучше завершить/перезапустить зависшее приложение, чем оставлять его на самотёк. Это негативно сказывается на юзабилити и усложняет сбор сведений о сбоях для дальнейшего анализа. А Вы можете подтвердить Ваши слова кодом? (хотя бы псевдокодом)Код
Название: Re: потоки Отправлено: CPP11 от Декабрь 09, 2014, 18:27 Igors, это зависит от контекста. Часто нужно сохранить промежуточное состояние приложения и после перезапуска попытаться вернуть его в это состояние. Естественно нужно зафиксировать сам факт падения и информацию, которая может помочь выявить причину - обычно это дамп процесса(чаще минидамп + состояние объектов), если программа полагается на сторонние компоненты, то имеет смысл сохранить и информацию о них. После перезапуска приносим извинения пользователю и отправляем себе отчёт об ошибке (некоторые приложения просят пользователя подтвердить отправку, т.к. в таких дампах может содержаться приватная информация).
Название: Re: потоки Отправлено: Igors от Декабрь 09, 2014, 18:49 Igors, это зависит от контекста. Часто нужно сохранить промежуточное состояние ... Ну и что Вы будете сохранять в данном случае? Откуда Вы возьмете промежуточное состояние - или вообще хоть какую-то информацию достойную сохранения/посылки? И почему такая ситуация вообще расценивается как "падение"? Нитка не завершилась через 1 секунду? Так что с того, такое вполне вполне возможно если напр было распределено гораздо больше памяти чем физически имеет хилая машина, или хороший файл мапнут в память (вындоуз пошла по свопам).Так зачем врать самому себе надеясь что ну когда-то (в будущем) Вы напишете тонну кода для обработки этой ситуации? В лучшем случае это будет assert который потом уберут. Здесь нет конструктивного выбора, и это лучше признать сразу. Название: Re: потоки Отправлено: CPP11 от Декабрь 09, 2014, 19:41 Ну и что Вы будете сохранять в данном случае? Да элементарно - тут нужно завершить приложение, так что просто убиваем свой процесс, а ОС всё подчистит. В противном случае получим зависшее окно, которое будет мозолить глаза пользователю, который его рано или поздно убьёт, вспоминая вас добрым словом. А если окна не будет, то процесс просто будет висеть и жрать ресурсы, пока система не перезагрузится, что ещё хуже.Нитка не завершилась через 1 секунду? не надо цепляться к этой цифре, можно выбрать свою в зависимости от ситуации, в моём случае подвисать там нечему, поэтому выбран период, который не позволит пользователю заетить подвисание. Возможно, 5 секунд будет лучшим выбором для Windows, чтобы дождаться повышения приоритета на случай загруженности процессора. Как бы то ни было, это оффтоп, вопрос был не о выборе времени ожидания завершения процесса. |