Модераторы: Poseidon, Snowy, bems, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Почему зависает поток? 
:(
    Опции темы
Poseidon
Дата 15.4.2014, 09:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

Репутация: 53
Всего: 133



Цитата(PointerToNil @  15.4.2014,  02:16 Найти цитируемый пост)
вот только зачем вызывающий поток-то для этого останавливать? 
 А если ситуация, когда потоку надо обратиться к VCL несколько раз подряд? Как без блокируещего метода и без бубна гарантировать, что предыдущее обращание завершилось?

Цитата(PointerToNil @  15.4.2014,  02:16 Найти цитируемый пост)
конечно нет, как же это, совсем без критических секций что ли?? 
Т.е. если один поток отрабатывает критическую секцию, второй поток не ждет на входе в нее? Второй поток не простаивает? Это чем-то принципиально отличается от Synchronize?

Цитата(PointerToNil @  15.4.2014,  02:16 Найти цитируемый пост)
ну как бы сразу напрашивается переменные/поля на 3 состояния, сигнализирующие о том, что обработка данной порции данных еще не начата/начата/уже закончена или 2 переменные - счетчики числа взятых на обработку элементов и числа уже обработанных (причем синхронизировать доступ к ним (interlocked*) нужно только для операции установки состояния "взято на обработку" или увеличения счетчика взятых на обработку, только между несколькими потоками-обработчиками и только в случае, если их несколько, а VCL-поток волен читать их в любой момент) - но для кого-то это может показаться слишком простым и низкоуровневым, [sarcasm] тут же без пары крутых специальных классов с дюжиной методов не обойтись [/sarcasm] 
Ну да, реально проще наворотить с три короба кода, придумать крутые алгоритмы с переменными, сигнализированием, счетчиками, но ни за что не пользоваться Synchronize. А в чем разница, или поток будет крутить в холостую цикл, ожидая когда же нужная переменная примет нужное значение, что бы пойти дальше, или поток остановится, ожидая Synchronize?

Цитата(PointerToNil @  15.4.2014,  02:16 Найти цитируемый пост)
а вот и возможное решение (из второй ссылки):
Это не решение, а один из вариантов. Если потоку надо "вбросить" данные в VCL и идти дальше (как в случае автора), то Queue подойдет. А если потоку надо работать с данными VCL, то тут нужна гарантия что кто-то другой (поток или даже сам пользователь) не поменял эти данные в процессе.

А теперь самое интересное. У UKRtortik в Synchronize одна строчка кода, которая обрабатывается за долю секунды. Неужели блокировка потока на эту долю секунды и есть то самое "зависание" о котором пишет UKRtortik? Неужели если мы отправим в VCL неблокирующее сообщение вместо Synchronize, то поток не "зависнет"? Там по коду отчетливо видно, что поток посылает Get в сеть и ждет ответ. Вот это ожидание и есть причина. А Synchronize там вообще не при чем.

Модератор: Давайте вернёмся к теме обсуждения.


--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
Romikgy
Дата 15.4.2014, 09:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 26
Всего: 146



F7 & F8


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
PointerToNil
Дата 15.4.2014, 10:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



*


Профиль
Группа: Участник
Сообщений: 108
Регистрация: 17.6.2013

Репутация: 3
Всего: 6



Poseidon> А если ситуация, когда потоку надо обратиться к VCL несколько раз подряд? Как без блокируещего метода и без бубна гарантировать, что предыдущее обращание завершилось?
это гарантируется тупо тем, что поток VCL только один и, естественно, обращения к нему выстраиваются в очередь (ну загляни в classes.pas что ли уже, если ссылки tl;dr)

Poseidon> Т.е. если один поток отрабатывает критическую секцию, второй поток не ждет на входе в нее? Второй поток не простаивает? Это чем-то принципиально отличается от Synchronize?
да. отличается по области применения. критические секции (или атомарный доступ к предложенным мной переменным-признакам или счетчикам) нужны для сериализации (очередизации) доступа к данным среди потоков-копий из одной группы/пула - они могут за эти данные конкурировать, например, пытаться одновременно "забрать" себе на обработку один очередной необработанный блок.
а в ситуации как у ТС, когда "рабочий" поток уже обработал блок данных и он ему больше не нужен, поток следующего этапа (занимающийся выводом) может его спокойно (если этот поток в одном экземпляре) забирать, он должен только о его готовности узнать либо по переменной-признаку, либо по сообщению в своей очереди. без конкуренции потоков синхронизация гораздо проще (нет толкотни соседей по очереди) 

Poseidon> Ну да, реально проще наворотить с три короба кода, придумать крутые алгоритмы с переменными, сигнализированием, счетчиками
да никаких "алгоритмов" тут нет! самое сложное тут - это 
Код

if flag[i] = ReadyForProcessing then begin {блок [i] готов к обработке и свободен - попытаемся занять}
  old_flag := InterlockedExchange(flag[i], InProcessing); {атомарный обмен}
  if old_flag <> ReadyForProcessing then {опаньки, кто-то опередил на микросекунду и занял раньше нас!} continue
    else {ок, занято нами} begin
    {Processing here}
    flag[i] := ProcessingCompleted; {можно менять уже без предосторожностей}
    {тут можно сделать PostMessage окну, обработчик сообщений которого выводит информацию и т.п.}
    end;
  end;
{если пробежали в цикле по всем i и у всех ProcessingCompleted - то завершаем тред, а если ни одного Ready то можно и поспать}
ну а написав "с три короба" лишь один раз, нормальный программист обернет это как следует, чтобы в другой раз просто вызвать метод/функцию
(обычно это успевают сделать за нас еще в Микрософте/Борлакадеро, и там у них внутри те же примитивные переменные и циклы)

Poseidon> А в чем разница, или поток будет крутить в холостую цикл, ожидая когда же нужная переменная примет нужное значение, что бы пойти дальше, или поток остановится, ожидая Synchronize?
предполагается, что "крутить цикл" будет ожидающий данных (пока еще не готовых) поток второго этапа (вывода и т.п.), а останавливать по Synchronize я не хочу потоки первого этапа ("рабочие"), к которым навалом других сырых данных в очереди ещё стоит (если вдруг наоборот, в очереди на вывод скопление образуется, то и крутить вхолостую ничего не придется)

Poseidon>А если потоку надо работать с данными VCL, то тут нужна гарантия...
да что же это такое то?!?! с данными VCL номинально разрешено работать только потоку VCL. к счастью, он у нас только один
гарантий же от глупости программиста никакие волшебные классы/методы/функции никогда не дадут
в частности, Synchronize блокирует только свой собственный поток (думаете, авторы VCL предполагали, что программист, только что послушно выполнив их рекомендации и вызвав правильный метод, может ТУТ ЖЕ СРАЗУ уйти в отрыв и с горя полезть в VCL напрямую, поэтому и решили это дело заблокировать?!? сорри за эмоции, если что) 
при этом Synchronize ничуть НЕ блокирует ВСЕ остальные потоки (вообще по-хорошему только сам поток может себя "поставить на паузу", как и закончить, хотя через winapi... но это не рекомендуется)

Модератор: Давайте вернёмся к теме обсуждения.
а без тредстартера основная тема все равно пока WaitingForSingleObject

Это сообщение отредактировал(а) PointerToNil - 15.4.2014, 12:16
PM MAIL   Вверх
Poseidon
Дата 15.4.2014, 12:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

Репутация: 53
Всего: 133



Цитата(PointerToNil @  15.4.2014,  10:39 Найти цитируемый пост)
это гарантируется тупо тем, что поток VCL только один и, естественно, обращения к нему выстраиваются в очередь (ну загляни в classes.pas что ли уже, если ссылки tl;dr)
Отлично. Поток отдает VCL данные, что бы VCL их применил, и идет дальше. А дальше нужно эти данные прочитать. Поток считывает данные, наивно предполагая, что предыдущий код их изменил. Но вот незадача, наредивый пользователь влез своими руками и поменил что-то. И получилось у нас, что поток считал уже не те данные, которые ожидались. Ах да, можно же нагородить кучу проверок, флагов, блокировок, но Synchronize использовать ну никак нельзя.

Цитата(PointerToNil @  15.4.2014,  10:39 Найти цитируемый пост)
да никаких "алгоритмов" тут нет! самое сложное тут - это 
"Это" - 10 строк кода в примитивной реализации. Synchronize займет одну.

Цитата(PointerToNil @  15.4.2014,  10:39 Найти цитируемый пост)
ну а написав "с три короба" лишь один раз, нормальный программист обернет это как следует, чтобы в другой раз просто вызвать метод/функцию
Нормальные программисты уже обернули подобные велосипеды в Synchronize, Queue прочие методы TThread. Но богата земля русская умельцами, которые неприемлят буржуйские традиции.

Цитата(PointerToNil @  15.4.2014,  10:39 Найти цитируемый пост)
а без тредстартера основная тема все равно пока WaitingForSingleObject
Очень хочется увидеть код, который через WaitingForSingleObject заставит поток, который отправляет Get запрос, выполнятся без задержек. Пока это больше похоже на пустой треп. Автор стросил причину, ему причину указали. И эта причина совершенно не в использовании Synchronize.


 ! 
Poseidon
Обсуждение целесообразности использования Synchronize в данной теме является нарушением пункта 9 Правил форума. Сообщения в данной теме, являющиеся ответами на мои цитаты, будут расценены как провокация к нарушению Правил и будут удалены на основании пункта 3.


PointerToNil, если есть желание обсудить никчемность Synchronize, можешь создать для этого отдельную тему.


--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
UKRtortik
Дата 15.4.2014, 15:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 24.3.2014

Репутация: нет
Всего: нет



Цитата

Автор стросил причину, ему причину указали.

Извините я возможно не заметил, ну где мне указали причину?
PM MAIL   Вверх
Poseidon
Дата 15.4.2014, 15:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

Репутация: 53
Всего: 133



Цитата(UKRtortik @  15.4.2014,  15:33 Найти цитируемый пост)
где мне указали причину? 
 
Цитата(Poseidon @  14.4.2014,  16:57 Найти цитируемый пост)
Вполне возможно что поток стартует быстро, и останавливается на HTTPSend.HTTPMethod. Я уже писал, "зависание" на HTTPSend вполне объяснимо.




--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
UKRtortik
Дата 15.4.2014, 15:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 24.3.2014

Репутация: нет
Всего: нет



а что с этим делать?
PM MAIL   Вверх
stanilar
Дата 15.4.2014, 17:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 9.2.2010

Репутация: нет
Всего: нет



Tесли HTTPSend - это Indy, то у ней может быть свой механизм потоков, с странным поведением которого вы и сталкиваетесь. 
PM MAIL   Вверх
Poseidon
Дата 15.4.2014, 17:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

Репутация: 53
Всего: 133



Цитата(UKRtortik @  15.4.2014,  15:38 Найти цитируемый пост)
а что с этим делать? 
 
Цитата(Romikgy @  14.4.2014,  17:07 Найти цитируемый пост)
интернет мощнее



--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
UKRtortik
Дата 15.4.2014, 21:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 24.3.2014

Репутация: нет
Всего: нет



user posted image


этого что недостаточно?
PM MAIL   Вверх
Poseidon
Дата 15.4.2014, 22:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

Репутация: 53
Всего: 133



А покажи пинг того ресурса, куда отправляется Get.


--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
PointerToNil
Дата 16.4.2014, 08:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



*


Профиль
Группа: Участник
Сообщений: 108
Регистрация: 17.6.2013

Репутация: 3
Всего: 6



Poseidon, я все же сделаю еще одну попытку объяснить недопонятое, потому, что иначе затраченные нами обоими на этот разговор усилия оказываются совсем бесполезными. А так остаётся маленькая надежда.

Те приведенные 10 строк - вовсе не замена synchronize, они нужны для совсем другого случая - а именно, для сериализации доступа к данным между конкурирующими за них потоками (перечитайте абзац, где упоминается конкуренция). Там synchronize не применим никак, так как разбираться друг с другом должны несколько рабочих (неглавных) потоков! (обычно их число = числу ядер или *2 для гипертрединговой архитектуры). Участвует ли в этой конкуренции еще и главный (VCL) поток или нет - значения не имеет. 
Interlocked* функции (пример в тех 10 строках) - облегченная замена критическим секциям для случаев, когда нужна одноразовая атомарная операция с переменной/полем простого типа.

А вот TThread.Queue - отличный вариант (как замена synchronize), я как раз за него! (если он есть в вашей версии дельфей)

"без тредстартера основная тема все равно пока WaitingForSingleObject" - перевожу на русский: без тредстартера основная тема все равно пока зависла в ожидании одного объекта, т.е. тредстартера (это была попытка пошутить)

BTW, собрал и запустил код тредстартера - никакие "подвисания" не проявились

Это сообщение отредактировал(а) PointerToNil - 17.4.2014, 12:58
PM MAIL   Вверх
CynicRus
Дата 16.4.2014, 09:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 248
Регистрация: 31.5.2012

Репутация: нет
Всего: 5



Цитата(UKRtortik @ 15.4.2014,  15:33)
Цитата

Автор стросил причину, ему причину указали.

Извините я возможно не заметил, ну где мне указали причину?

Яж тебе говорил - под отладчиком пошагово посмотри, где у тебя тормозит. Как пользоваться отладчиком? Можно заценить тут.
PM MAIL   Вверх
UKRtortik
Дата 16.4.2014, 15:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 24.3.2014

Репутация: нет
Всего: нет



а как понять из-за чего зависает в открадчике? Зависать начинает на этой строке:

Код

Thread Start: Thread ID: 4276. Process Project1.exe (5356)

PM MAIL   Вверх
PointerToNil
Дата 16.4.2014, 18:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



*


Профиль
Группа: Участник
Сообщений: 108
Регистрация: 17.6.2013

Репутация: 3
Всего: 6



UKRtortik, тебе нужно найти строку в коде программы, исполнение которой тормозит
1 поставь breakpoint (F5) на первой после begin строке TNewThread.Execute
2 запусти программу (F9), в ней - свой тред, дождись срабатывания брейкпоинта (открытия экрана дельфи)
3 теперь жми F8 и следи за задержкой (между скрытием и новым появлением экрана дельфей, обычно это мерцание даже не успеваешь заметить) - многократно, пока не найдешь (или до выхода из метода)
PM MAIL   Вверх
Страницы: (4) Все 1 2 [3] 4 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1014 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.