Имя: Пароль:
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) "ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Дата, ТипЦен = &ТипЦен) КАК ЦеныНоменклатурыСрезПоследних
                          |            ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют.СрезПоследних(&Дата, ) КАК КурсыВалютСрезПоследних
                          |            ПО ЦеныНоменклатурыСрезПоследних.Валюта = КурсыВалютСрезПоследних.Валюта"
зачем соединять все цены со всеми курсами валют? Поправьте этот момент, получите заметное ускорение
Здесь можно обсудить любую тему при этом оставаясь на форуме для 1Сников, который нужен для работы. Ymryn