Ожидание инициализации переменной.

1. Aleksey_Abramov 08.02.24 14:10 Сейчас в теме
В клиентской процедуре модуля формы есть переменная МояКомпонента. Необходимо дождаться, пока она инициализируется и только потом продолжить выполнение кода. При этом, чтобы это не было более 8 секунд. Как это лучше сделать? У меня такая мысль, но чувствую, что это не совсем рационально:
Если МояКомпонента = Неопределено Тогда
	ВремяНачалаОжидания = ТекущаяУниверсальнаяДатаВМиллисекундах();
	Пока МояКомпонента = Неопределено Цикл
		Если ТекущаяУниверсальнаяДатаВМиллисекундах() - ВремяНачалаОжидания > 8 Тогда
			Сообщить("Компонента не инициализирована, попробуйте позже");
			Прервать;
		КонецЕсли;
	КонецЦикла;
	
КонецЕсли;

Если МояКомпонента = Неопределено Тогда
	Возврат;
КонецЕсли;

МояКомпонента.Метод4();
Показать
По теме из базы знаний
Ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
3. ActionBlog 08.02.24 15:31 Сейчас в теме
(1)Вариант 1 - https://infostart.ru/1c/articles/1158171/
Вариант 2 (очень требовательный к ресурсам)-
сек = 300;
КонДата = ТекущаяДата() + сек;
  Пока ТекущаяДата() < КонДата Цикл
      // ждемссс....
  КонецЦикла;


Вариант 3 -
 Процедура глПауза(Сек)
scr = Новый COMОбъект("WScript.Shell");
scr.Run("sleep "+СокрЛП(Число(Сек)),0,1);
КонецПроцедуры; 
4. dakork 33 08.02.24 16:19 Сейчас в теме
(1)
Если стоит винда то можешь использовать это - оно менее требовательно к ресурсам
Процедура Пауза(Интервал = 8) Экспорт
	
	Компьютер=".";
	Локатор=Новый COMОбъект("wbemscripting.swbemlocator");
	Сервис=Локатор.ConnectServer(Компьютер,"root\cimv2","","","","",128);
	Время = Сервис.ExecNotificationQuery("Sel ect * fr om __instancemodificationevent WITHIN 1 where TargetInstance isa 'Win32_LocalTime' and TargetInstance.Second="+Секунда(ТекущаяДата()+Интервал));
	СледующееСобытие = Время.NextEvent();
	
	
КонецПроцедуры
Показать
2. Rettro 08.02.24 15:21 Сейчас в теме
Используй подключаемую процедуру в которой каждую секунду проверять свою переменную

Изучи - ПодключитьОбработчикОжидания()
5. Aleksey_Abramov 08.02.24 17:44 Сейчас в теме
(2) Обработчик ожидания выполняется. Но код идёт дальше. Как сделать, чтобы модуль ждал ожидание этого обработчика?
6. Rettro 08.02.24 18:40 Сейчас в теме
(5)
Процедура ПодключаемОбработчик()

        ПодключитьОбработчикОжидания("ОбработчикОжиданияТест",1);

КонецПроцедуры

Процедура ОбработчикОжиданияТест()
          Если МояКомпонента <> Неопределено Тогда
                   МояКомпонента.Метод4();
                    ОтключитьОбработчикОжидания("ОбработчикОжиданияТест");
          КонецЕсли;
КонецПроцедуры
Показать
7. Serega-artem 17 08.02.24 18:43 Сейчас в теме
Мои пять копеек. Не претендую сильно на оригинальность.

1. Создайте общую переменную Завершить, присвойте ей ложь.
2. Создайте процедуру ПрерватьИнициализацию в которой присваиваете Завершить = Истина;
3. Запустить ОбработчикОжидания процедуры ПрерватьИнициализацию на 8 сек. и однократным выполнением.
4. Запустить процедуру с кодом

Пока МояКомпонента = Неопределено или НЕ  Завершить цикл 
КонецЦикла; 


В плане оптимизации и нагрузки такое себе, но в 1с с ожиданиями вообще мрак.
8. Rettro 08.02.24 18:55 Сейчас в теме
(3) и (7) : оба этих варианта блокируют выполнение кода, а будучи вызванным из клиентского кода, заблокирует пользовательский интерфейс.
9. Serega-artem 17 08.02.24 18:56 Сейчас в теме
(8) Как бы

Необходимо дождаться, пока она инициализируется и только потом продолжить выполнение кода.
10. Rettro 08.02.24 19:00 Сейчас в теме
(9) Но зачем блокировать вообще всю систему + пользователь не может работать с программой
11. Serega-artem 17 08.02.24 19:08 Сейчас в теме
(10) Тут надо у ТС уточнять, чего он вообще хочет. На самом деле все варианты в общем-то такие себе, внятного способа решить это силами 1с нет и это очень плохо. Уже лет 15 только на моей памяти идут разговоры о нормальной паузе средствами языка, но воз и ныне там.

Все из предложенных решений создают нагрузку. Либо постоянно запускать обработчик ожидания, потом еще и отключать его, либо постоянно системное время получать и высчитывать. Я исходил из того, что как только компонента станет доступна мы сразу же идем дальше. Ну, а через 8 сек. это прерываем. И это не идеальное решение, но думаю не хуже остальных.

Кстати, еще вопрос о том как вообще идет инициализация компоненты, возможно не с той стороны копаем.
12. Aleksey_Abramov 08.02.24 19:56 Сейчас в теме
(11) В общем сделал так, оставляю тут, как заметку для себя. В веб клиенте пока работает всё как надо. Всем спасибо за идеи =)

&НаКлиенте
Процедура КомандаПечать(Команда)
	
	// Тут начинается асинхронная инициализация компоненты
	Если Не ОбщийМодульРаботаСОборудованием.ПроинициализироватьМоюКомпоненту() Тогда 
		Возврат;
	КонецЕсли;
	
	ВремяОжиданияСекунд = 8; // Это реквизит формы, тип Число
	ПодключитьОбработчикОжидания("ПроверитьИнициализациюКомпоненты", 1, Ложь);
	
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьИнициализациюКомпоненты()
	
	Если ВремяОжиданияСекунд < 1 Тогда		
		ОтключитьОбработчикОжидания("ПроверитьИнициализациюКомпоненты");
		ТекстСообщения = НСтр("ru = 'Не удалось инициализировать компоненту оборудования.'");
		ОбщегоНазначенияКлиент.СообщитьПользователю(ТекстСообщения);		
	ИначеЕсли Не ГлобальныеКомпоненты.Свойство("МояКомпонента") Тогда // ГлобальныеКомпоненты - структура компонент (глобальная переменная в модуле приложения)		
		// Продолжаем ожидание
		ВремяОжиданияСекунд = ВремяОжиданияСекунд - 1;		
	Иначе // Компонента МояКомпонента инициализирована		
		ОтключитьОбработчикОжидания("ПроверитьИнициализациюКомпоненты");
		// Продолжаем работать с компонентой
		ВыполнитьПечать();
	КонецЕсли;

КонецПроцедуры

&НаКлиенте
Асинх Процедура ВыполнитьПечать()
	
	МояКомпонента = ГлобальныеКомпоненты.МояКомпонента;
	МояКомпонента.Метод4Async();
	// ...

КонецПроцедуры
Показать
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот