|
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
|
|||||||||||||||||||||||||||
Синхронизация асинхронного заполения списка и CancellationToken06.10.2021, 14:07. Показов 8443. Ответов 95
Метки нет (Все метки)
Открываю GUI страницу со списком картинок.
Проблема: из-за того, что картинки весят много -- какое-то время, допустим 2 секунды, страница просто пустая, а после резко заполняется всем списком. Желаемый результат: хотелось бы, чтобы при открывании страницы элементы постепенно подгружались. Решение 1: решил сделать само заполнение асинхронным (просьба сначала досмотреть все 3 решения)
Решение 2: добавил локировку
Решение 3: я подумал, что во время закрытия страницы будет уместным сделать cancelTokenSource.Cancel();
Добавлено через 9 минут Также хотел упомянуть следущий момент:
0
|
|||||||||||||||||||||||||||
| 06.10.2021, 14:07 | |
|
Ответы с готовыми решениями:
95
BlockingCollection<T>, Add(T item, CancellationToken cancellationToken); Зачем нужен CancellationToken? Не происходит отмена задачи (CancellationToken) |
|
Модератор
|
|||
| 10.10.2021, 02:46 | |||
|
И кроме прочего, возврат по одному элементу с DbContext приведёт к отдельному запросу к БД для каждого элемента. Это точно не стоит делать. Если для очень большой коллекции, потребуется выбирать страницами (в GUI тогда надо будет реализовывать виртуализацию), то тогда будет возвращаться некий диапазон элементов. Добавлено через 2 минуты За его границами из него невозможно получить данные.
0
|
|||
|
1522 / 508 / 126
Регистрация: 09.01.2018
Сообщений: 1,541
|
||||||||
| 10.10.2021, 02:58 | ||||||||
1
|
||||||||
|
Модератор
|
||||||||
| 10.10.2021, 09:06 | ||||||||
|
Распараллелить надо именно создание представлений, ну и оптимизировать само представление. Выше были предоставлены тайминги исполнения: пост #41, пост #45 и пост #54. Посмотрите сами. Добавлено через 8 минут Как вы его можете применить к такому (по сути) методу:
1
|
||||||||
|
1522 / 508 / 126
Регистрация: 09.01.2018
Сообщений: 1,541
|
||
| 10.10.2021, 09:37 | ||
|
Я же не знаю деталей, как там реализован этот метод GetDevices, что именно он делает по пути, может он грузит картинки откуда то с сервера, может еще что делает. Задержки то есть. Поэтому остаются только предположения.Добавлено через 17 минут И потом, насколько я понимаю, если UI тратит много времени на отображение одной картинки, то на 10 картинок он потратит в 10 раз больше. Значит они будут медленно, по одной, с ощутимой задержкой появляться, а не все разом после длительной задержки.
1
|
||
|
Модератор
|
|||||
| 10.10.2021, 10:28 | |||||
|
Именно с этим нюансом и пытаемся разобраться. Можно добавить сразу весь диапазон в одной задаче. Тогда на время добавления UI поток будет занят и представление будет строиться сразу для всех добавленных элементов. Можно в отдельных задачах добавлять по одному элементу. Тогда между задачами добавления, основной поток будет строить представление для добавленного элемента и они в GUI будут добавляться по одному. С местом где возникают задержке разобрались в начале темы. Что подтверждают тайминги на которые я вам дал ссылки. Добавлено через 3 минуты Почему простой прямоугольник создаётся почти 50 мс? Какая-то особенность Xamarin? Или тестовое устройство очень медленное?
1
|
|||||
|
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
|
|||||||||||||||||||||||||||
| 10.10.2021, 14:42 [ТС] | |||||||||||||||||||||||||||
и тогда у меня IsCancellationRequested будет true, но уже после проверки, а следовательно следующее условие выполнится. Я думаю такое вероятно, поэтому локировку я оставлю.
Кроме как методом "тыка" я уж не знаю как ещё. Лично я грешу на сам INotyfiPropertyChanged -- реализацию. Возможно она, из-за изобилия событий OnPropertyChanged, которые даже не используются, немного нагружает UI каким-то образом (уж из крайности в крайность). Добавлено через 11 минут На данный момент вот такая реализация Кликните здесь для просмотра всего текста
Если я правильно понял, для AsyncObservableCollection я меняю private Task UpdateDevicesWithCancellationTokenChecker(CancellationToken token) => Task.Run(() =>на private async Task UpdateDevicesWithCancellationTokenChecker(CancellationToken token) => await Task.Run(async() =>Оставляю Device.InvokeOnMainThreadAsync, а так как он асинхронный и в локировке, то его запись оставляю без изменений вот так Task.Run(async () => await Device.InvokeOnMainThreadAsync(() => Devices.Clear()));И общий код следующий
0
|
|||||||||||||||||||||||||||
|
Модератор
|
||||||||||
| 10.10.2021, 15:49 | ||||||||||
|
Тогда так:
Если на них подписки нет (то ест нет отображения этих свойств), то поднятие в других потоках PropertyChanged никак не влияет на GUI. Добавлено через 3 минуты И посмотрите как быстро отработает GUI отражающий эту коллекцию. Для элемента задайте такое же представление как в вашем приложении. Если тормозов не будет, то придётся перелопачивать ваше приложение и искать в чём причина тормозов. Добавлено через 4 минуты Тогда вам нужно при изменении условия поиска id = currentDevice == null ? Root : currentDevice.Id, тоже отменять предыдущий токен, создавать новый и вызывать метод для нового условия с новым токеном.
1
|
||||||||||
|
1522 / 508 / 126
Регистрация: 09.01.2018
Сообщений: 1,541
|
||
| 10.10.2021, 16:02 | ||
|
2
|
||
|
Модератор
|
|||||||||||||
| 10.10.2021, 16:07 | |||||||||||||
|
Task.Run - просто ставит задачу в очередь пула. А когда выполнится эта задача - неизвестно. Конечно, в большинстве случаев это происходит достаточно быстро. Но это не гарантированно. Вполне возможно что задача начнётся выполняться уже после прекращения локировки или даже после выхода из вашего основного метода. Внутри лока должен быть только синхронный код. В этом случае можно сделать так:
С учётом использования AsyncObservableCollection, наверное всё же так:
Пишу в редакторе сообщения - могут быть ошибки.
1
|
|||||||||||||
|
1522 / 508 / 126
Регистрация: 09.01.2018
Сообщений: 1,541
|
|||||||
| 10.10.2021, 17:18 | |||||||
|
Вот например:
Даже если в методе GetImageAsync выставить Task.Delay(50), вывод все равно будет плавным.
2
|
|||||||
|
Модератор
|
||
| 10.10.2021, 18:33 | ||
|
Я же вам давал ссылки на тайминги исполнения. Задержка получаются не при извлечении данных из БД (ил откуда там они получаются? - это не важно), а при добавлении извлечённых данных в коллекцию, привязанную в Представлении. Кроме того InMemory поможет при частых обращениях к БД за одними и теми же данными, которые не изменяются внешне. Но если при каждом обращении требуются разные данные или эти данные постоянно меняются извне, то чем здесь может помочь InMemory? Всё равно при каждом запросе будет происходить запрос к реальной БД за реальными данными. По коду же понятно, что есть коллекция Devices отражающая какие-то данные. В методе делается очередной снимок (кадр) данных и потом по этому снимку нужно обновить Devices. Допустим, в очередном кадре нет какого-то элемента из Devices и значит нужно его удалить. НО!!! чтобы понять, что его нет в кадре, нужен целиком этот кадр. Что толку от последовательного получения отдельных элементов кадра? Добавлено через 2 минуты escoult, я нисколько не спорю с вами, что есть случаи когда лучше реализовывать с использованием InMemory и IEnumerable. Но конкретно эта задача не относится к таким случаям. Посмотрите внимательнее на код и объяснения в топике. Там же сразу понятно, что и для чего делается.
0
|
||
|
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
|
||||||
| 10.10.2021, 18:39 [ТС] | ||||||
|
Элд Хасп, тут ничего не понял
? Root : currentDevice.Id. А функция возращает тип boll, тогда как понять какой должен быть результат: Root или Id. Во-вторых, Guid -- это структура и как я понял, там == null -- излишнее, ибо оно относится к id в том числе, как я понимаю, а id -- не объект типа DeviceViewModel -- это Guid.
0
|
||||||
|
1522 / 508 / 126
Регистрация: 09.01.2018
Сообщений: 1,541
|
|||||
| 10.10.2021, 18:47 | |||||
|
0
|
|||||
|
Модератор
|
|||||||||||||||||
| 10.10.2021, 19:05 | |||||||||||||||||
|
Но суть в другом. При входе в метод вы получили какой-то id. Именно он определяет условия запроса. При изменении условий запроса (то есть этого id) нужно прервать метод или нет? Если нужно то тогда надо проверять сохранённый id на соответствие с текущими условиями. Если это не нужно, или если у вас это уже обрабатывается при отмене токена, то удалите этот метод и проверяйте только токен. если id не равен ... или токен отменён, то возвращается true и значит надо прервать метод. Вот добавил скобки, чтобы вам было понятно:
Я же писал вам уже, что код тормозит на простых Frame, со слов TC. limeniye, напишите что у вас выводится в представлении элемента. Есть там картинки или нет? Лучше ещё бы и скрин выложили. Добавлено через 4 минуты Последовательно проверяется Devices и каждый элемент ищется в полученном кадре Если его нет в кадре, то он удаляется из Devices. 53-я строка:
Ничего ждать не надо. Надо только обновить её по очередному кадру.
0
|
|||||||||||||||||
|
1522 / 508 / 126
Регистрация: 09.01.2018
Сообщений: 1,541
|
|||
| 10.10.2021, 19:15 | |||
|
Добавлено через 1 минуту Добавлено через 8 минут Если бы, к примеру ТС написал фейковый репозиторий с готовой коллекцией, без картинок и подставил бы его вместо основного репозитория, можно было бы твердо сказать да-нет.
0
|
|||
|
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
|
||||||||||||||||||||||||||
| 10.10.2021, 19:28 [ТС] | ||||||||||||||||||||||||||
|
Элд Хасп, касательно метода, приложенного тут: очень быстро прогружает элементы один за одним, но вот если возвращаю отображение картинки -- прогружает также один за одним, но весь список прогружает дольше.
Отображение картинки следующее: срабатывает событие PropertyChanged кастомного свойства EntityProperty, туда, как я понимаю, передают тот самый объект DeviceViewModel, внутри которого есть Guid-id картинки.
И в ней меня очень сильно смущают следующие методы:
Device.BeginInvokeOnMainThread -- добавление в пулл, как я понял. А не его асинхронный аналог.Все методы, кроме следующего, синхронные void
var photoDocument = await Task.Run(() => _simpleClient.Documents.GetDocument(documentId)); вот тут по Guid id-шнику отправляется запрос на получение фото.Сам же метод вызывается следующим образом:
Может Вы понимаете, почему так. Да и вообще, там объект приходит в событие и из события запускаются другие методы, в которых Device.BeginInvokeOnMainThread(() и Task.Run(() => GetDocument(documentId)); запускается без async await ![]() Добавлено через 4 минуты Я уже пытался это асинхронизировать -- но результата это абсолютно никакого не дело. Добавлено через 7 минут .
0
|
||||||||||||||||||||||||||
|
Модератор
|
||||
| 10.10.2021, 19:31 | ||||
|
Метод рассчитан именно на обновление коллекции, а не на её замену. В само начале - это действительно полная запись кадра в коллекцию. Но записываются УЖЕ ГОТОВЫЕ элементы. Записываются по одному. Для каждого создаётся своё событие CollectionChanged. И для каждого элемента строится отдельно своё представление. И тормоза именно в построении этого представлении, а не в том как получается кадр. С получением кадра всё Ок, ничего там оптимизировать не нужно. Если вы в XAML убираете представление для этого GUID, то всё нормально, без лагов работает? Метод GetDocument возвращает Stream, который отправляется прямиком ... в мусор. Никто этот Stream не использует. Мне, кажется, что если вы закомментарите тело метода GetPersonImage, то ничего измениться не должно. Ну, или вы не тот код выложили.
0
|
||||
|
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
|
|||
| 10.10.2021, 19:36 [ТС] | |||
|
0
|
|||
|
Модератор
|
|||
| 10.10.2021, 19:42 | |||
|
Поэтому обычного сравнения операторами равенства-неравенства достаточно. Добавлено через 2 минуты Надо разбираться каким образом в Представлении по полученному GUID извлекается картинка. Добавлено через 3 минуты limeniye, картинки какой элемент представляет? Image? Если да то ему ImageSource нужны. Их надо готовить в отдельных задачах, замораживать и потом передавать в Image.
1
|
|||
|
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
|
|||||||||||||
| 10.10.2021, 19:49 [ТС] | |||||||||||||
|
То есть было так
Если добавляю эту строку: страница открывается без лагов, элементы добавляются один за одним, список тоже могу скроллить, но вот заполнение списка занимает уже не 7 секунд, а 25.
0
|
|||||||||||||
| 10.10.2021, 19:49 | |
|
Помогаю со студенческими работами здесь
80
Данные об отделах ( процент заполения )
Почему CancellationToken не сбрасывает Token Проверка на правильность заполения полей Отправка формы после проверки заполения reCAPTCHA Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
||||
|
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта
Симптом:
После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
|
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
|
Новый ноутбук
volvo 07.12.2025
Всем привет.
По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне:
Ryzen 5 7533HS
64 Gb DDR5
1Tb NVMe
16" Full HD Display
Win11 Pro
|
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
|
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
|
|
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов
На странице:
https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/
нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
|
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов.
. . .
|
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
|
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
|
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут.
В век Веб все очень привыкли к дизайну Single-Page-Application .
Быстренько разберем подход "на фреймах".
Мы делаем одну. . .
|