|
19.12.2016, 16:33 | #1 |
Участник
|
Многопоточное вычисление дисплейных методов
Привет всем!
Столкнулся с одной формой, на которой навешано куча тяжелых дисплейных методов. Из-за которых блокировалась работа пользователей. cacheAddMethod не сильно помогал, так как даже первый незакешированный вызов блокирует интерфейс на несколько десятков секунд при каждой прокрутке страницы на гриде. Целью моих экспериментов было создать такое кеширование дисплейных методов, которое не блокирует пользовательский интерфейс даже при первой прорисовке данных. Во вложении проект для AX2012. В проекте есть тестовая форма, которая демонстрирует использование многопоточного вызова дисплейных методов. Данные перерисовываются не сразу, а постепенно, как будто вы находитесь на веб-странице. На тестовой форме представлен пример вызова дисплейного метода, возвращающего вещественное число, и дисплейного метода, возвращающего строку. Чтобы применить пример к любой другой форме, надо 1) Добавить на вашу таблицу все кешируемые дисплейные методы, которые есть на вашей форме, но нет в вашей таблице 2) Вызвать эти дисплейные методы из дисплейных методов на вашей форме, используя предлагаемый пример. В тесте вызываются дисплейные методы "grossWeight" и "itemName" из таблицы InventTable 3) с тестовой формы взять те участки кода, которые обрамлены комментариями X++: //Дисплейные методы --> ........ //Дисплейные методы <-- На дисплейные методы формы точки останова ставить можно, т.к. они выполняются в главном потоке. Последний раз редактировалось Ace of Database; 19.12.2016 в 17:37. |
|
|
За это сообщение автора поблагодарили: mazzy (2), AlGol (3), sukhanchik (4), Logger (3), gl00mie (5), Dreadlock (5), dech (3), nYury (1). |
19.12.2016, 16:52 | #2 |
Участник
|
а выводить данные из формы в эксель будет?
а в отчет можно? а в экспорт во внешние системы? |
|
19.12.2016, 17:04 | #3 |
Участник
|
Цитата:
2) Фишка в том, что на форме реализован таймер, который достает время от времени вычисленные в других потоках данные. Поэтому отчет можно сформировать только как слепок данных с формы 3) То же самое, что и пункт 2 |
|
19.12.2016, 17:21 | #4 |
Участник
|
Обновил проект.
Пофиксил интересный баг с повторным использованием переменной типа AnyType, инициализированной для другого типа данных. В результате переставало работать, если на одной и той же форме были строковые и числовые дисплейные методы Последний раз редактировалось Ace of Database; 19.12.2016 в 17:27. |
|
19.12.2016, 17:54 | #5 |
Участник
|
|
|
20.12.2016, 12:11 | #6 |
Участник
|
Цитата:
Алгоритм вычисления прогресса не до конца совершенен, но в принципе достаточно нагляден. Последний раз редактировалось Ace of Database; 20.12.2016 в 14:03. |
|
|
За это сообщение автора поблагодарили: mazzy (2). |
19.12.2016, 17:26 | #7 |
Участник
|
И еще раз обновил
|
|
20.12.2016, 13:37 | #8 |
Мрачный тип
|
Интересная идея.
2012-й под рукой нет, зырил код через блокнот и вполне мог упустить кое-что, но тем не менее осталось впечатление, что механизма обновления кэша нет, т.е. после обновления записи (в т.ч. полей, на основе которых рассчитывается дисплейный метод) будет возвращаться то же самое значение. В принципе это можно реализовать дополнительной мапой { [tableId, recid] -> recVersion} по отработанным табличным переменным. При несовпадении recVersion у отработанной табличной переменной (по данным доп. мапы) и переданной - чистить кэш по ней и запускать отработку метода снова с обновлением результата в кэше и доп.мапе.
__________________
Мы летаем, кружимся, нагоняем ужасы ... Последний раз редактировалось TasmanianDevil; 20.12.2016 в 13:39. |
|
20.12.2016, 13:53 | #9 |
Участник
|
Механизм очистки кеша целиком есть, в примере он просто не использован
Чтобы очистить весь кеш и заставить все вычисляться заново, надо вызвать метод clearCache() в классе zThreadDisplayMethod Очистка кеша для отдельных записей для меня не представляется полезной, т.к. такие дисплейные методы обычно работают очень быстро, и вычислять их в отдельном потоке не имеет смысла. Но, если все-таки надо очистить кеш только для нужной записи в таблице для конкретного дисплей-метода, то можно удалить запись из двух мапов - mapResult и mapCalled класса zThreadDisplayMethod. А также из таблицы zThreadResultTable для того же самого ключа, что и для мапов, но еще дополнительно отфильтровав по коду сессии, который хранится в переменной session в классе zThreadDisplayMethod. |
|
20.12.2016, 13:57 | #10 |
Участник
|
Я оговорился, в примере полная очистка кеша используется. В методах ExecuteQuery() и Research() в источнике данных на форме. То есть, подразумевается, что раз пользователь нажал F5, то все надо заново пересчитать.
|
|
28.02.2017, 12:09 | #11 |
Участник
|
Выяснилось, что метод cacheAddMethod на источнике данных формы вызывает один раз дисплейный метод для каждой отображаемой записи. Даже если поле скрыто на форме.
Поэтому, если используется самописное кеширование дисплейных методов через Map, то лучше убрать cacheAddMethod. А при использовании мгногопоточности вообще получается плавная прокрутка данных на форме. |
|
Теги |
thread, проекты |
|
|