|
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
|
|||||||||||||||||||||||||||
Синхронизация асинхронного заполения списка и CancellationToken06.10.2021, 14:07. Показов 8430. Ответов 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) |
|
Модератор
|
|
| 06.10.2021, 14:23 | |
|
limeniye, обычно разделяют загрузку коллекции Uri (или других источников) картинок и загрузку самих картинок.
Второе происходит только после обращения к ним в UI. Вы уже вроде пытались использовать решение из Асинхронная подгрузка изображений Что не получилось? В данном, случае вы пытаетесь в Модели угадать действия UI и соответственно провести их обработку. Тем самым у вас возникает паразитная зависимость Модели от UI. Схема должна быть очень простая. У Модели запросили данных - он их отдала. Если получение коллекции данных долгий процесс, надо возвращать коллекцию идентификаторов (имён, ссылок, Uri, путей и т.д.). А основные данные для каждого элемента возвращать отдельным методом по запросу для каждого элемента.
1
|
|
|
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
|
||
| 06.10.2021, 15:04 [ТС] | ||
|
Начну с того, что в данном случае это не Модель, а ViewModel. Я использую паттерн MVVM. Стандартом MVVM, для меня, является следующая схема: Но если зайти в гугл и написать "схема mvvm" -- то самым популярным будет абсолютно другая: Лично моё мнение: мне второй способ не нравится, я считаю его полным нарушением самого принципа MVVM(субъективное мнение). Но именно второй способ реализован во всём легаси проекте. Касательно Асинхронная подгрузка изображений. Конкретно этот проект -- Xamarin, в нём нет того же image.Freeze()Всё вышеперечисленное не имеет особого смысла, ибо загрузка изображений в проекте происходит из VM в Code-Behind. При чём код-бихайнд, от части, выступает в качестве ViewModel, но наследуется от Grid. Возможно я бы и попытался использовать вышепредложенный Вами способ, но в этом участке архитектуры я бы ничего не менял, ибо тот же Code-Behind ИЗОБРАЖЕНИЯ (под изображение выделили отдельный контрол) содержит 632 строки. Надеюсь я достаточно расписал проблему, почему я делаю асинхронность добавления элементов в список аж на уровне VM. Потому что всё что ниже -- какая-то каша, я ничего не понимаю, сложно читать, сложно расширять. Зная то, как хорошо Вы разбираетесь в MVVM -- боюсь даже рассказывать подробности архитектуры -- Вам потом будут сниться кошмары.
0
|
||
|
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
|
|
| 06.10.2021, 15:12 [ТС] | |
|
Всё, что ниже этой VM, -- каша, я стараюсь на уровне этой VM хоть как-то всё оптимизировать (да, вот таким я вижу решение из этой ситуации).
0
|
|
|
Модератор
|
||
| 06.10.2021, 15:37 | ||
|
Вернее это MVVM, но в ней неверные обозначения блоков. То что называют Моделью - это отражение БД. А Модель (из паттерна приложения) здесь просто не обозначена и к ней относится репозиторий и всё что с ним связано. Составлял кто-то имеющий опыт работы с БД в разных паттернах, и применивший (не совсем верно) свой опыт для составления этой якобы MVVM схемы. Добавлено через 1 минуту Если открыть доки MS (а MVVM разработан ими), то там видно что нет никаких репозиториев, а Моделью называется всё что "ниже" ViewModel.
0
|
||
|
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
|
|||||||
| 06.10.2021, 16:13 [ТС] | |||||||
|
У меня на работе первый паттерн вообще первый раз видят: как разработчики WPF проектов, так и разработчики UWP. ________________________________________ ________________________________________ __________________ В данный момент я смирился с тем, что модель есть далеко не всегда и далеко не всё что модель -- настоящая модель. А следовательно вернусь к теме. Конкретно в ТС уже каша на моей стороне и я это объективно понимаю. Можете глянуть? Напомню желаемый результат: чтобы можно было асинхронно добавлять элементы в список, но потокобезопасно, а также при переключении на прошлую страницу остановить асинхронный поток Я это делал так
0
|
|||||||
|
Модератор
|
|||
| 06.10.2021, 19:19 | |||
|
И всё что делает Модель - это обеспечивает работу с Репозиторием. Кроме того, Репозиторий это тоже Модель. И не никакого криминала в том, что VM будет работать напрямую с Репозиторием без каких-то промежуточных слоёв. Скорее всего, те с кем вы общались, имеют дело только с такими проектами, в которых нужна реализация GUI для работы с БД. Если появляется хоть малейшая Бизнес Логика, то (настоящая) Модель неминуемо возникнет. Давайте по пунктам: 1) Есть некая коллекция Devices, которая каким-то образом представлена в GUI: - Что за тип элементов этой коллекции? - Можете ли вы менять его реализацию? - Как синхронизируется эта коллекция с привязками? - Есть ли необходимость в изменении коллекции поэлементно или она всегда меняется целиком? 2) Метод UpdateAll: - Чей это член: VM? Модели? - Должен одновременно работать только один вызов метода? - Если да, то что должно происходить при повторном вызове: исключение, ожидание, прерывание предыдущего? 3) Картинки: - Где они находятся и в каком типе? - Как и в каком типе передаёте их Представлению?
1
|
|||
|
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
|
|||||||||||||||||||||||||||||||||||||||
| 06.10.2021, 20:46 [ТС] | |||||||||||||||||||||||||||||||||||||||
|
1)
3)
либо отправляет какой-то запрос, либо берёт локально. Если отталкиваться от Вашего вопроса: какого он типа, то на этот вопрос сложно ответить, по коду он получается обобщённым. Его пихают сюда:
.
0
|
|||||||||||||||||||||||||||||||||||||||
|
Модератор
|
||||||
| 06.10.2021, 21:02 | ||||||
|
Эта тема была больше ради любопытства и познания. Реализация не практична. Добавлено через 2 минуты А где сама картинка? Добавлено через 1 минуту Добавлено через 1 минуту Этого будет достаточно. Добавлено через 1 минуту А у вас подвешивается GUI на секунды. Разница в три порядка. Где конкретно возникает пробблема?
0
|
||||||
|
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
|
||||||||||||
| 06.10.2021, 21:06 [ТС] | ||||||||||||
|
Один из примеров:
Но может быть не SKCanvasView, а обычный Image. А если берётся фото откуда-то локально, то ещё какой-то тип.
0
|
||||||||||||
|
Модератор
|
|||||||||||||||||||
| 06.10.2021, 21:24 | |||||||||||||||||||
|
Он должен отдавать готовую картинку АСИНХРОННО, чтобы не подвешивать GUI. Должно быть нечто подобное: Свойство задающее ID картинки.
Добавлено через 1 минуту Добавлено через 4 минуты Как это согласует с вашим из-за того, что картинки весят много -- какое-то время, допустим 2 секунды, страница просто пустая?Добавлено через 59 секунд limeniye, чё то у меня складывается впечатление, что вы сами не знаете в чём проблема и просто наугад бахаете то туда, то сюда.
2
|
|||||||||||||||||||
|
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
|
|||||||||||||
| 06.10.2021, 21:51 [ТС] | |||||||||||||
|
Я понимаю, но тут всё это на стороне код-бихайнд. Чтобы сделать, что делаете Вы -- нужно поднять весь кодбихайнд в VM. Там 600 строк, я не хочу компаться в этом несколько дней. Методом тыка, по какой-то неизвестной мне причине, асинхронизация следующего кода... с
Не их картинки, Вы правильно уточнили, а именно сами элементы уже с отрисованными картинками. Почему так? -- мне не ясно, но я хочу пока закрепить этот вариант, потом уже думать над другим. Как я хочу его закрепить? Я хочу сделать потокобезопасность этого варианта или схожего.
0
|
|||||||||||||
|
Модератор
|
||
| 06.10.2021, 23:24 | ||
Сообщение было отмечено limeniye как решение
РешениеРаботает? Используйте его, если вы не хотите глубоко залазить. Только вот с токеном отмены - по-моему, неправильно используете. Его же надо в задачу передавать: Task.Run(Action, CancellationToken).
1
|
||
|
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
|
|
| 07.10.2021, 00:12 [ТС] | |
|
Элд Хасп, спасибо. Всё то, что ожидал услышать (с первого ответа до текущего).
Тут хотел бы прокомментировать. Я уже был на этой ссылке и там всё делается в одном методе, как и на многих других ссылках. Это малоинформативно для меня. Вот это я как раз и не понимаю как бы правильней сделать, ибо у меня один метод отменяет, второй запускает. Я сам вижу, что делаю не совсем так, да ещё и он у меня срабатывает 1 раз, а потом когда я открываю снова страницу — он остаётся Canceled ибо у меня его реализация кривая.
0
|
|
|
Модератор
|
|
| 07.10.2021, 02:16 | |
|
limeniye, ну, так весь смыл его в том, что если экземпляр отменён, то остаётся всегда отменённым.
То есть вам надо определиться по алгоритму, когда надо завершить текущий токен - это повлечёт отмену всех задач. Отменённый экземпляр активировать заново невозможно. Когда вам нужно следующий раз его активировать, то нужно создавать новый экземпляр. Добавлено через 1 минуту Когда вы переходите на новую страницу, вы сначала отменяете текущий экземпляр. Потом создаёте новый экземпляр. Заменяете им текущий. И после этого все запускаемые задачи будет использовать новый экземпляр.
1
|
|
|
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
|
|||||||||||||||||
| 07.10.2021, 02:35 [ТС] | |||||||||||||||||
Ибо как это вижу я: при выходе из страницы я отменяю текущий экземпляр, а на входе — создаю новый. Вход на страницу.
0
|
|||||||||||||||||
|
Модератор
|
|||||||
| 07.10.2021, 03:09 | |||||||
|
limeniye, у меня нет понимания структуру вашего проекта и поэтому я не понимаю где всё это надо сделать.
Но последовательность такая. 1) Создали экземпляр токена; 2) Его используют все задачи которые может потребоваться отменить; 3) Когда токен отменяются - завершаются все задачи которые его использовали; 4) Токен нужно уничтожить (Dispose). Вот этотм момент не могу сказать точно, когда следует делать. Толи можно сразу после отмены, толи надо дождаться завершения всех задача его использующих; 5) Когда потребуется создать следующую очередь задач, то сначала создаётся новый экземпляр токена и им замещается уничтоженный. У меня очень сильные сомнения, что вы верно используете здесь асинхронность. Посмотрите что вы делаете: 1) У вас идёт асинхронное получение коллекции devices: 2) Потом вы асинхронно по ней меняете коллекцию (наверное свойство) Devices; 3) Пока изменяете Devices вы производите локировку. НО! Изменение привязанной коллекции (если вы используете мою реализацию AsyncObsevable) будет происходить в основном потоке. Вы пишите, что такая реализация не подвешивает GUI. Следовательно, с высокой долей вероятности, изменение Devices (пункты 2 и 3) происходят очень быстро. А раз так, то и встраивать в них токен отмены нет смысла. Скорее всего у вас тормозит метод devicesRepository.GetDevices (пункт 1). Вы его сделали асинхронным и этого достаточно. Пункты 2 и 3 надо выполнять уже просто в методе - без задачи, так как они всё равно по факту выполняются в основном потоке. Попробуйте проверить на тормоза такую реализацию:
Тогда её можно будет менять из любого потока.
1
|
|||||||
|
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
|
|||||||||
| 07.10.2021, 10:54 [ТС] | |||||||||
|
Элд Хасп, да, Devices это свойство { get; }
Касательно
Далее я поставил точки остановка на каждый цикл, чтобы проверить — какой самый медленный. Но если отдельно проверить все циклы — то каждый проходит быстро, но если запустить точку останова от строки 1 до 36 — 3 секунды занимает. Я могу предположить, что проблема в том, что Devices — это коллекция NotifyPropertyChanged свойств и из-за этого может происходить какие-то проблемы (например двойное изменение одного свойства где-то в архитектуре), или что-то в этом роде (сугубо предположение). Добавлено через 1 час 37 минут Протестировал следующую запись:
0
|
|||||||||
|
Модератор
|
|||
| 07.10.2021, 11:08 | |||
|
Уточните: 1) Devices - обычная ObservableCollection и используете синхронизацию привязок к ней? 2) Каковы (примерно) размеры Devices и devices? Добавлено через 7 минут devicesRepository.GetDevices, то он не должен возвращать null.Если данных нет, то он должен возвращать пустую коллекцию.
1
|
|||
|
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
|
||||||||||||||||||||||
| 07.10.2021, 12:16 [ТС] | ||||||||||||||||||||||
|
Элд Хасп, провёл некоторое тестирование.
Попробовал поставить ObservableCollection, оставить await.Task и локировку. Результат: подтормаживает. Элементы отображаются уже прогруженными.
Результат: очень странное поведение, подтормаживает, но редко. Элементы отображаются уже прогруженными.
Попробовал поставить AsyncObservableCollection, оставить await.Task и локировку. Результат: не подтормаживает. Элементы прогружаются один за одним.
Результат: страница подрормаживает. А потом элементы отображаются уже прогруженными.
0
|
||||||||||||||||||||||
| 07.10.2021, 12:16 | |
|
Помогаю со студенческими работами здесь
20
Данные об отделах ( процент заполения )
Почему 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 .
Быстренько разберем подход "на фреймах".
Мы делаем одну. . .
|