Имя: Пароль:
1C
1С v8
Функционирование асинхронной функции
,
0 Dragonofdwarfs
 
04.10.22
10:43
Всем привет! Друзья, подскажите пожалуйста, можно ли написать асинхронную функцию в 1с в рамках такой задачи: При открытии самописной расширенной формы списка номенклатуры я создаю ТЗ параметров номенклатуры с колонками: ссылка, параметр, индексирую её по ссылке, чтобы поиск был моментальным, помещаю её в реквизит формы. При активизации строки пользователем, данные в табличную часть параметров очищаются и моментально пробрасываются по текущей ссылке. Всё звучит отлично, только вот форма открывается долго, порядка 7 секунд, и во всём виновато создание этой ТЗ. Так вот, я хочу поместить создание этой тз в асинх функцию, чтобы форма открылась гораздо быстрее, а тз с параметрами подтянулась чуть позже,т.е чтобы пользователь мог уже работать с формой. Написал всё по науке, но выполнение получается синхронным, т.е дополнительный поток исполнения кода не появляется, форма всё так же ждёт создания этой тз и затем открывается. Как быть? Как правильно написать асинх функцию, чтобы она работала как надо?
1 Dragonofdwarfs
 
04.10.22
10:50
Так выглядит например моя тестовая обрабока по этим асинх функциям, но выполнение всё так же синхронное, т.е сначала выполняется код, возвращающий сообщение о значении итератора, а потом выводится 123 и сообщение, а по идее должен пойти выполняться код, затем сразу же должно вывестись сообщение 123, а затем как асинх функция отработает - сообщение о значении итератора!

&НаКлиенте
Асинх Процедура КнопкаВыполнитьНажатие(Кнопка)
    
    Результат = ВывестиСообщениеОЗначенииИтератораАсинх();                          
    
    Сообщить("123");
    Сообщить(Ждать Результат);
    
КонецПроцедуры

&НаКлиенте
Асинх Функция ВывестиСообщениеОЗначенииИтератораАсинх()
      
    Сч = 0;
    Пока Сч < 1000000 Цикл
        Сч = Сч + 1;    
    КонецЦикла;

    Возврат("Значение итератора = " + Сч);          
    
КонецФункции
2 Dragonofdwarfs
 
04.10.22
10:59
Такое ощущение, что модуль асинх нужен чисто как синтаксический сахар, чтобы описывать оповещение об окончании исполнения какого-то участка кода
3 polosov
 
04.10.22
11:12
(0) Странный подход конечно.
Попробуй фоновым заданием формировать свою таблицу.
4 lodger
 
04.10.22
11:22
а) ты не понял зачем нужен асинх
б) асинх не надо использовать для попытки создать многопоточность
в) сделай это по классике - фоновое задание и обработчик ожидания
5 Мультук
 
гуру
04.10.22
11:25
6 Dragonofdwarfs
 
04.10.22
11:35
Но так фоновое задание не запишет  же эту таблицу в реквизит открытой формы в другом сеансе!
7 polosov
 
04.10.22
11:39
(6) ФЗ вернет тебе адрес в хранилище на твою ТЗ. Получишь ее и передашь в реквизит.
8 lodger
 
04.10.22
11:45
(0) когда ТЗ является реквизитом формы, то у неё нет индексов. можешь не индексировать.
9 mTema32
 
04.10.22
11:47
(0) "Процедура КнопкаВыполнитьНажатие(Кнопка)" - на обычных формах штоле?
10 Мультук
 
гуру
04.10.22
11:48
(0)

7 секунд. Там что-то совсем ? Или как всегда пользователь хочет взглянуть на таблицу и 1млн строк ?
11 Dragonofdwarfs
 
04.10.22
11:49
(9) да, на обычных
12 Dragonofdwarfs
 
04.10.22
11:50
(8) адрес в хранилище? Что это значит, куда и как мне сохранить эту тз?
13 Мультук
 
гуру
04.10.22
11:53
(12)

Лучше покажи код формирования это тз
Возможно там можно что-то оптимизировать

Сколько строк то хоть получается ?
14 Dragonofdwarfs
 
04.10.22
11:54
(10) По факту то, что я описал выше занимает 4,5 секунды, но форма открывается 7, потому что там ещё другие данные подтягиваются
15 Dragonofdwarfs
 
04.10.22
11:58
Вот код, который несёт максимальную нагрузку


Функция ПолучитьТаблицуДопРеквизитовНоменклатуры(МассивНоменклатуры = Неопределено) Экспорт

    Если МассивНоменклатуры = Неопределено Тогда
        Запрос = Новый Запрос("ВЫБРАТЬ
                              |    ТарифныеКоэффициентыПроизводителейСрезПоследних.Коэффициент КАК Коэффициент,
                              |    ВЫБОР
                              |        КОГДА КурсыВалютСрезПоследних.Курс <> 1
                              |            ТОГДА ЦеныНоменклатурыСрезПоследних.Цена * (ВЫРАЗИТЬ(КурсыВалютСрезПоследних.Курс + 0.5 КАК ЧИСЛО(10, 0))) * 1.03
                              |        ИНАЧЕ ЦеныНоменклатурыСрезПоследних.Цена
                              |    КОНЕЦ КАК Тариф,
                              |    ТарифныеКоэффициентыПроизводителейСрезПоследних.Коэффициент * ВЫБОР
                              |        КОГДА КурсыВалютСрезПоследних.Курс <> 1
                              |            ТОГДА ЦеныНоменклатурыСрезПоследних.Цена * (ВЫРАЗИТЬ(КурсыВалютСрезПоследних.Курс + 0.5 КАК ЧИСЛО(10, 0))) * 1.03
                              |        ИНАЧЕ ЦеныНоменклатурыСрезПоследних.Цена
                              |    КОНЕЦ КАК ЦенаРасчетная,
                              |    СпрНоменклатура.Ссылка КАК Ссылка,
                              |    СпрНоменклатура.Подгруппа КАК Подгруппа,
                              |    СпрНоменклатура.КатегорияНоменклатуры КАК Категория
                              |ИЗ
                              |    Справочник.Номенклатура КАК СпрНоменклатура
                              |        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Дата, ТипЦен = &ТипЦен) КАК ЦеныНоменклатурыСрезПоследних
                              |            ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют.СрезПоследних(&Дата, ) КАК КурсыВалютСрезПоследних
                              |            ПО ЦеныНоменклатурыСрезПоследних.Валюта = КурсыВалютСрезПоследних.Валюта
                              |        ПО СпрНоменклатура.Ссылка = ЦеныНоменклатурыСрезПоследних.Номенклатура
                              |        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ТарифныеКоэффициентыПроизводителей.СрезПоследних(&Дата, ) КАК ТарифныеКоэффициентыПроизводителейСрезПоследних
                              |        ПО (СпрНоменклатура.Ссылка = ТарифныеКоэффициентыПроизводителейСрезПоследних.Номенклатура
                              |                И СпрНоменклатура.Производитель = ТарифныеКоэффициентыПроизводителейСрезПоследних.Производитель)");
        Запрос.УстановитьПараметр("Дата", ТекущаяДата());
        Запрос.УстановитьПараметр("ТипЦен", Справочники.ТипыЦенНоменклатуры.НайтиПоНаименованию("Тариф"));
        Результат = Запрос.Выполнить().Выгрузить();
        Результат.Индексы.Добавить("Ссылка");
        
        Возврат(Результат);
    КонецЕсли;
    
    
    Запрос = Новый Запрос("ВЫБРАТЬ
                          |    Номенклатура.Ссылка КАК Ссылка,
                          |    Номенклатура.Подгруппа КАК Подгруппа,
                          |    Номенклатура.КатегорияНоменклатуры КАК КатегорияНоменклатуры
                          |ПОМЕСТИТЬ СпрНоменклатура
                          |ИЗ
                          |    Справочник.Номенклатура КАК Номенклатура
                          |ГДЕ
                          |    Номенклатура.Ссылка В(&МассивНоменклатуры)
                          |;
                          |
                          |////////////////////////////////////////////////////////////////////////////////
                          |ВЫБРАТЬ
                          |    ТарифныеКоэффициентыПроизводителейСрезПоследних.Коэффициент КАК Коэффициент,
                          |    ВЫБОР
                          |        КОГДА КурсыВалютСрезПоследних.Курс <> 1
                          |            ТОГДА ЦеныНоменклатурыСрезПоследних.Цена * (ВЫРАЗИТЬ(КурсыВалютСрезПоследних.Курс + 0.5 КАК ЧИСЛО(10, 0))) * 1.03
                          |        ИНАЧЕ ЦеныНоменклатурыСрезПоследних.Цена
                          |    КОНЕЦ КАК Тариф,
                          |    ТарифныеКоэффициентыПроизводителейСрезПоследних.Коэффициент * ВЫБОР
                          |        КОГДА КурсыВалютСрезПоследних.Курс <> 1
                          |            ТОГДА ЦеныНоменклатурыСрезПоследних.Цена * (ВЫРАЗИТЬ(КурсыВалютСрезПоследних.Курс + 0.5 КАК ЧИСЛО(10, 0))) * 1.03
                          |        ИНАЧЕ ЦеныНоменклатурыСрезПоследних.Цена
                          |    КОНЕЦ КАК ЦенаРасчетная,
                          |    СпрНоменклатура.Ссылка КАК Ссылка,
                          |    СпрНоменклатура.Подгруппа КАК Подгруппа,
                          |    СпрНоменклатура.КатегорияНоменклатуры КАК Категория
                          |ИЗ
                          |    СпрНоменклатура КАК СпрНоменклатура
                          |        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Дата, ТипЦен = &ТипЦен) КАК ЦеныНоменклатурыСрезПоследних
                          |            ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют.СрезПоследних(&Дата, ) КАК КурсыВалютСрезПоследних
                          |            ПО ЦеныНоменклатурыСрезПоследних.Валюта = КурсыВалютСрезПоследних.Валюта
                          |        ПО СпрНоменклатура.Ссылка = ЦеныНоменклатурыСрезПоследних.Номенклатура
                          |        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ТарифныеКоэффициентыПроизводителей.СрезПоследних(&Дата, ) КАК ТарифныеКоэффициентыПроизводителейСрезПоследних
                          |        ПО (СпрНоменклатура.Ссылка = ТарифныеКоэффициентыПроизводителейСрезПоследних.Номенклатура
                          |                И СпрНоменклатура.Ссылка.Производитель = ТарифныеКоэффициентыПроизводителейСрезПоследних.Производитель)");
    Запрос.УстановитьПараметр("Дата", ТекущаяДата());
    Запрос.УстановитьПараметр("ТипЦен", Справочники.ТипыЦенНоменклатуры.НайтиПоНаименованию("Тариф"));
    Запрос.УстановитьПараметр("МассивНоменклатуры", МассивНоменклатуры);
    Результат = Запрос.Выполнить().Выгрузить();
    Если Результат.Количество() > 10000 Тогда
        Результат.Индексы.Добавить("Ссылка");
    КонецЕсли;
        
    Возврат(Результат);
    
КонецФункции
16 Мультук
 
гуру
04.10.22
12:42
(15)

1) Индексы здесь не нужны. В данной ситуации - напрасная трата времени
2) В этом виде (выбрать всю номенклатуру) - оно быстрее работать не будет.
Вопрос в том, а точно нужно всё и сразу ?
3) Можно посмотреть в сторону "а как это сделано в Обработки.ПодборНоменклатуры"
4) Обычно в подобных формах стараются ограничить количество строк отборами


Прочее
а) Если вы используете  ЛЕВОЕ СОЕДИНЕНИЕ -- используйте ЕСТЬNULL, ибо дальше окажется, что пусто на экране вовсе не ноль
б) Между РегистрСведений.КурсыВалют.СрезПоследних(&ТекущаДата, ) и РегистрСведений.КурсыВалют.СрезПоследних(, )
есть разница. Она описана в ИТС
17 Dragonofdwarfs
 
04.10.22
13:29
(16) Спасибо огромное! Буду пробовать)
18 mistеr
 
04.10.22
14:42
(0) Оффтопик, но чем не устроили типовые возможности поиска номенклатуры?
19 rudnitskij
 
04.10.22
15:21
(15) "ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Дата, ТипЦен = &ТипЦен) КАК ЦеныНоменклатурыСрезПоследних
                          |            ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют.СрезПоследних(&Дата, ) КАК КурсыВалютСрезПоследних
                          |            ПО ЦеныНоменклатурыСрезПоследних.Валюта = КурсыВалютСрезПоследних.Валюта"
зачем соединять все цены со всеми курсами валют? Поправьте этот момент, получите заметное ускорение