nesco, благодарю за подробные разъяснения и примеры! Это настоящий рождественский подарок для hiasm-щика. На мультипоточную схему, пусть и непроверенную, с удовольствием посмотрю.
Редактировалось 1 раз(а), последний 2019-01-07 12:11:51
Этот топик читают: Гость
Ответов: 704
Рейтинг: 7
|
|||
карма: 0 |
|
Разработчик
Ответов: 26177
Рейтинг: 2128
|
|||
Neo писал(а): На мультипоточную схему, пусть и непроверенную, с удовольствием посмотрю.MultiDownLoadURL_006 Но нужно обновить HTTP_Get, я там ввел возможность менять UserAgent-a в RealTime-e. Редактировалось 1 раз(а), последний 2019-01-07 13:37:34 |
|||
карма: 22 |
| ||
файлы: 1 | MultiDownLoadURL_006.zip [7.9KB] [552] |
Ответов: 704
Рейтинг: 7
|
|||
Оптимизирую "джунгли" по новым "понятиям" о потоках. Стало уже стабильнее. Но разбираясь с примером выше, обнаружил что идет работа вообще без мьютексов. И обратился к штатному примеру, вспомнить как его вообще применять. Так получается что выводить в оконные элементы можно из параллельного потока прямо по onExec? Да и читать данные из того же Text тоже можно в параллельном потоке? Считал что обращаться к оконным элементам из параллельного вообще нельзя, только через синхронизированные с главным потоком события. Может есть что почитать на эту тему применимо к HiAsm?
Штатную схему прикрепляю.
|
|||
карма: 0 |
|
Разработчик
Ответов: 26177
Рейтинг: 2128
|
|||
Neo писал(а): Так получается что выводить в оконные элементы можно из параллельного потока прямо по onExec?Можно, но не нужно. Работает это крайне нестабильно. Neo писал(а): Да и читать данные из того же Text тоже можно в параллельном потоке?Это можно, команды на перерисовку контрола, в таком случае, не возникает. Neo писал(а): Но разбираясь с примером выше, обнаружил что идет работа вообще без мьютексовЕсли в моем примере, то там их отродясь и не было за ненадобностью, как, кстати, и вот этого там тоже нет Neo писал(а): получается что выводить в оконные элементы можно из параллельного потока прямо по onExec?Neo писал(а): Штатную схему прикрепляюХа, тебя сбивает с толку управление из потока напрямую контролами, но так это просто пример. В основных, стабильных схемах так лучше не делать. Редактировалось 4 раз(а), последний 2019-01-08 03:13:27 |
|||
карма: 22 |
|
Ответов: 704
Рейтинг: 7
|
|||
nesco, благодарю! Супер-понятно и подробно.
|
|||
карма: 0 |
|
Ответов: 4634
Рейтинг: 751
|
|||
nesco писал(а): внутренним методом Sender.Synchronize(SyncExec), а сам продолжает выполняться дальше ... те параллельный поток не ждет окончания события главного потокаРедактировалось 1 раз(а), последний 2019-01-08 13:19:03 |
|||
карма: 26 |
|
Разработчик
Ответов: 26177
Рейтинг: 2128
|
|||
Netspirit писал(а): А он использует SendMessage()Елки, а ведь точно. Тогда поток повиснет на время работы обработчика главным потоком. Вот почему поток работает с интерфейсным и элементами. Какие у тебя по этому вопросу мысли? Редактировалось 1 раз(а), последний 2019-01-08 17:09:34 |
|||
карма: 22 |
|
Ответов: 4634
Рейтинг: 751
|
|||
nesco писал(а): Какие у тебя по этому вопросу мысли?Редактировалось 4 раз(а), последний 2019-01-08 15:03:53 |
|||
карма: 26 |
|
Разработчик
Ответов: 26177
Рейтинг: 2128
|
|||
Получается так, что onSyncExec и Synchronize вызывают обработчик главного потока и ждут завершения его работы. Но на время обработки сообщений главным потоком параллельный поток останавливается и ничего не может делать параллельно. Вот мне тут не понятен один момент -- а что, если интерфейсный элемент задержится с обработкой сообщений, а лимит времени остановки параллельного потока закончится? Или этот лимит бесконечен? Ты по этому вопросу, случаем, ничего не знаешь?
|
|||
карма: 22 |
|
Ответов: 16884
Рейтинг: 1239
|
|||
Видит бог - долго терпел.
Neo писал(а): Столкнулся с тем, что таблица строк на 7 строк по 38 колонок каждая ощутимо тормозит главный поток при полной перерисовке через замену строк. ![]() Оказывается вроде нет. Neo писал(а): Просто каждые 3 секунды данные в таблице полностью обновляются и к таблице имеют доступ через матрицу строк или массив строк другие участки схемы Neo, вопросы: 1. Зачем другим участкам схемы визуальная таблица строк? 2. Кому нужна 3-х секундная моргалка на экране? Редактировалось 2 раз(а), последний 2019-01-08 21:14:43 |
|||
карма: 25 |
|
Ответов: 704
Рейтинг: 7
|
|||
Tad, создавал программу давно когда еще трава была зеленее. Сейчас перестраиваю все под новый контроллер и под новые принципы. Таблица осталась изначально как отображение текущего положения дел. Иногда нужно ее посмотреть. Хотя сейчас планирую данные переносить в невизуальную матрицу строк и массив строк - так ведь надежнее? Но в таблице так удобно было с ними работать и наблюдать. Придется периодически перечитывать массив в таблицу для наблюдения. А вот сама таблица почему-то долго перерисовывается на некоторых вин10, пока не понял в чем дело.
|
|||
карма: 0 |
|
Ответов: 16884
Рейтинг: 1239
|
|||
Neo, вин10 32,64 ? Памяти сколько ?
|
|||
карма: 25 |
|
Ответов: 704
Рейтинг: 7
|
|||
Х64, памяти 8ГБ. По удаленке единственное, проверяю. Но на моем ноуте тоже х64 есть мелкие подвисания главного потока из-за талицы. В Вашем примере стабильно 10 событий/сек, а у меня та же схема 8-12 плавает если ее двигать активно. При этом ВинXPх86 с 2ГБ памяти даже намека на подвисания не дает и по удаленке. Пробовал на 10 отключать эффекты визуальные - ничего не меняет.
Редактировалось 4 раз(а), последний 2019-01-09 00:57:36 |
|||
карма: 0 |
|
Разработчик
Ответов: 26177
Рейтинг: 2128
|
|||
Neo писал(а): Пробовал на 10 отключать эффекты визуальные - ничего не меняет.Попробуй для проверки принудительно включить высокий приоритет графики для своего приложения -- Win+I -> Игры -> Игровой режим -> Настройки Графики. У меня и для HiAsm включен этот режим. Редактировалось 2 раз(а), последний 2019-01-09 02:43:17 |
|||
карма: 22 |
|
Ответов: 4634
Рейтинг: 751
|
|||
nesco писал(а): а что, если интерфейсный элемент задержится с обработкой сообщений, а лимит времени остановки параллельного потока закончится?Для посылки сообщения с таймаутом ожидания есть функция SendMessageTimeout(). Но этот вопрос не является каким-то особо принципиальным. Всё укладывается в принципы совместного доступа к какому-либо ресурсу ("синхронизации"): все конкурирующие потоки при доступе к общему ресурсу стают в ожидание (различными методами) освобождения ресурса, после чего по очереди получают эксклюзивный доступ. А задача программиста - правильно определить такие совместно используемые данные, обезопасить их, минимизируя "узкие места". По поводу последней схемы от Neo: всё же доступ к Edit, LED и прочим визуальным компонентам из параллельных потоков, как и говорил nesco, плохая идея. В целом ты вроде правильно используешь SafeMode, но, во-первых, "общими данными" для 2-х параллельных потоков является точка For.Position - первый SafeMode можно поставить только на запись этой точки, а второй - на чтение: чем меньше времени один поток занимает ресурс, тем меньше времени остальные потоки его ждут, тем больше полезных действий они выполнят параллельно. Во-вторых, работая с визуальными компонентами из параллельных потоков через SafeMode ты забываешь, что кроме твоих 2 явных потоков есть ещё и третий конкурирующий поток, обращающийся к тем же визуальным компонентам - главный поток приложения, обрабатывающий сообщения компонентам от системы. Это и является упомянутой выше проблемой доступа к визуальным компонентам из параллельных потоков. В некоторых случаях будет работать, а в некоторых будет давать ошибку. И SafeMode здесь не очень поможет - нужно использовать Synchronize, чтобы заставить ждать главный поток, пока параллельный поток работает с визуальным компонентом (на самом деле, "ждёт" параллельный поток, пока главный занимается исключительно его задачей, не отвлекаясь на другие сообщения). Небольшое рассуждение по поводу Application.doProcessMessages из параллельного потока. ![]() Механизм оконных сообщений Windows реализован таким образом.
Оконные сообщения обрабатываются некоторым потоком некоторого процесса. Следовательно, у этого потока есть некоторая очередь сообщений, куда система их складывает в порядке поступления. А как система знает какой поток какого процесса должен обработать сообщение данного окна? Ответ: тот поток, который и создал данное окно. Когда приложение однопоточное, при старте система создаёт один поток ("главный поток"). Этот поток создаёт все необходимые окна (например, главную форму приложения и тулбар с кнопками в ней). Затем входит в цикл выборки сообщений из своей очереди, а следовательно, только для созданных им самим окон. Например, от тулбара приходит сообщение клика на кнопку с индексом кнопки - главный поток ищет обработчик onClick данной кнопки, по которому, например, можно открыть другое окно. И хоть это другое окно "независимо" от главного (между ними можно переключаться, перемещать и т.д.), но тем не менее оно всё равно было создано главным потоком и его сообщения приходят и обрабатываются главным потоком. Что делает doProcessMessages - он просто принудительно делает выборку и обработку всех накопившихся сообщений теми же функциями, которыми это делает главный поток в цикле обработки сообщений. Вот только если делать doProcessMessages из главного потока, то сообщения будут обработаны, поскольку главный поток создавал окна и для него есть сообщения. А параллельный поток никаких окон не создавал и ему нечего обрабатывать. Собственно, задача doProcessMessages - например, принудительно перерисовать окно во время обработки какого-то пользовательского сообщения типа onClick: для перерисовки всех окон им надо послать сообщение WM_PAINT, но эти сообщения не будут обработаны пока мы не завершим обработку нашего клика. А нам уже срочно нужно показать пользователю, что по его клику что-то происходит в программе. В связи с выше изложенным можно провести любопытный эксперимент. Может кто замечал: если обычный Timer включить из параллельного потока, то события onTimer не будет - таймер реализован через сообщения, сообщения приходят создавшему ("включившему") его потоку, но поток не обрабатывает этих сообщений (или вообще сразу завершается). Но если после включения таймера в этом же потоке начать в цикле вызывать Application.doProcessMessages, то события у таймера начнут происходить (в этом же параллельном потоке). Наводящий вопрос: а можно ли "нормально" включить таймер из параллельного потока? Ответ - можно, "передав задачу" его включения главному потоку с помощью компонента Synchronize (или по Thread.onSyncExec). Редактировалось 18 раз(а), последний 2019-01-09 13:29:00 |
|||
карма: 26 |
| ||
Голосовали: | nesco |