При автоматизации производственных процессов, весовых терминалов и складских участков разработчики часто сталкиваются с задачей регулярного опроса оборудования. Например, необходимо каждые пару секунд считывать текущую температуру или вес с подключенных датчиков и показывать их оператору в окне документа. Когда показания стабилизируются, пользователь нажимает кнопку и фиксирует результат.
В платформе 1С 7.7 для периодического выполнения кода традиционно применяется процедура ОбработкаОжидания(). Однако при попытке вывести полученные цифры на открытую форму документа возникает неприятная проблема: стандартный метод Форма.Обновить() сбрасывает фокус и текущий ввод в активных ячейках или полях ввода к исходным значениям. Если же разработчик пытается перерисовать элементы через методы внешних компонент (например, FormEx), окно начинает сильно мерцать, а данные могут так и не обновиться. Разберем детально причины такого поведения платформы и выясним, как правильно организовать фоновый вывод показаний без помех для оператора.
Проанализируем механику работы стандартных методов обновления интерфейса в 1С 7.7:
Форма.Обновить() принудительно перечитывает значения всех реквизитов документа и элементов формы из памяти и базы данных. Если оператор в момент срабатывания таймера набирал текст или число в поле ввода, буфер редактирования очищается, а несохраненное значение сбрасывается.ОбработкаОжидания() запускает глобальный таймер на уровне всей сессии 1С. В платформе может одновременно работать только один такой таймер. Если он периодически инициирует общее обновление диалога, ввод данных оператором превращается в постоянную борьбу со сбросом значений.Наиболее простое, надежное и быстрое решение проблемы — отказаться от вызова Форма.Обновить() и менять текст конкретного элемента интерфейса напрямую. Для этого элементу диалога необходимо назначить уникальный идентификатор в конфигураторе.
Разберем реализацию этого подхода по шагам:
ПоказанияДатчика. Поле «Формула» при этом оставляем пустым.Форма и вызываем метод Заголовок().Посмотрим на пример реализации кода в модуле формы документа:
Перем мПериодОпроса;
// Процедура периодического опроса оборудования
Процедура ОпроситьДатчики()
Перем ТекВес, ТекТемпература, СтрокаИнфо;
// Получаем фактические данные от оборудования или драйвера
ТекВес = ПолучитьПоказанияВесов();
ТекТемпература = ПолучитьПоказанияТермометра();
СтрокаИнфо = "Вес: " + СокрЛП(ТекВес) + " кг | Темп: " + СокрЛП(ТекТемпература) + " °C";
// Точечно меняем надпись элемента без общего обновления формы
Форма.ПоказанияДатчика.Заголовок(СтрокаИнфо);
КонецПроцедуры
Процедура ПриОткрытии()
мПериодОпроса = 2; // каждые 2 секунды
ОбработкаОжидания("ОпроситьДатчики", мПериодОпроса);
КонецПроцедуры
Процедура ПриЗакрытии()
// Обязательно отключаем глобальный таймер при закрытии формы
ОбработкаОжидания("ОпроситьДатчики", 0);
КонецПроцедуры
Метод Форма.<Идентификатор>.Заголовок() напрямую посылает оконное сообщение операционной системы контролу диалога. Текст на экране меняется мгновенно, фокус ввода не теряется, а пользователь может продолжать непрерывный ввод данных в соседних полях документа.
Если на форме документа нет свободного места для размещения нового элемента диалога, можно использовать стандартные области отображения, которые не конфликтуют с редактированием реквизитов.
Рассмотрим два распространенных варианта:
Форма.Заголовок() позволяет динамически менять заголовок окна документа. Вы можете дополнять стандартное название документа актуальными цифрами.Состояние() выводит текст в нижнюю панель окна 1С и совершенно не затрагивает элементы диалога.Посмотрим на пример совместного использования этих методов:
Процедура ОпроситьДатчики()
Перем ТекВес, СтрокаИнфо;
ТекВес = ПолучитьПоказанияВесов();
СтрокаИнфо = "Текущий вес: " + СокрЛП(ТекВес) + " кг";
// Вариант А: меняем заголовок самого окна документа
Форма.Заголовок("Приходная накладная [" + СтрокаИнфо + "]");
// Вариант Б: дублируем информацию в статусную строку платформы
Состояние(СтрокаИнфо);
КонецПроцедуры
Хотя метод ОбработкаОжидания() удобен своей простотой, постоянный циклический опрос через таймер нагружает процессор и создает риск блокировки интерфейса в момент задержек ответа от COM-порта. Проанализируем более надежную архитектуру: подключение оборудования через штатный механизм внешних событий.
Большинство современных драйверов весовых индикаторов и датчиков поддерживают генерацию асинхронных событий Windows при стабилизации показаний. В этом случае платформе не требуется непрерывный таймер:
ОбработкаВнешнегоСобытия(Источник, Событие, Данные).Форма.ПоказанияДатчика.Заголовок(Данные) либо автоматически заполняет нужный реквизит документа.Использование метода Заголовок() в сочетании с корректным отключением таймеров в событии ПриЗакрытии() полностью устраняет проблему сброса полей ввода и обеспечивает комфортную работу оператора в 1С 7.7.