При активной многопользовательской работе в конфигурациях на обычных формах (таких как УПП или КА 1.1) периодически возникает трудноуловимая плавающая ошибка. Пользователь нажимает кнопку заполнения табличной части документа, после чего программа выдает сообщение: «Заполнение ТЧ не произведено! Метод объекта не обнаружен (Инициализировать)». При этом разработчик проверяет внешнюю обработку заполнения табличной части (ОЗТЧ) и видит, что экспортная процедура Инициализировать() присутствует в модуле объекта со всеми необходимыми параметрами. Интерактивная проверка под учетной записью того же пользователя в большинстве случаев проходит без сбоев.
Разберем природу этого поведения, выясним скрытую причину возникновения коллизии в терминальной среде и рассмотрим способы гарантированного устранения проблемы.
В типовых конфигурациях на обычных формах подключение внешних печатных форм и обработок заполнения табличных частей реализовано через общий модуль УниверсальныеМеханизмы. Проанализируем, как происходит вызов логики обработки:
ВнешниеОбработки.Создать(ИмяФайла) объект создается в оперативной памяти.Печать() — для печатных форм, либо Инициализировать() — для обработок заполнения табличных частей.В процедурах ОбработатьНажатиеНаДополнительнуюКнопкуЗаполненияТЧ и ПечатьПоДополнительнойКнопке разработчиками платформенных библиотек было заложено сохранение файла с жестко заданным именем PrnForm.tmp через конструкцию вида КаталогВременныхФайлов() + "PrnForm.tmp".
Рассмотрим ситуацию, когда множество сотрудников работают на терминальном сервере (RDS). В момент формирования печатной формы одним сотрудником двоичные данные печатной формы записываются в файл PrnForm.tmp. Если в эту же долю секунды другой пользователь (или тот же сотрудник во втором сеансе 1С) запускает обработку заполнения табличной части, возникает состояние гонки:
PrnForm.tmp печатную форму.PrnForm.tmp.ВнешниеОбработки.Создать() во втором процессе поднимает в память объект внешней печатной формы вместо обработки заполнения.Обработка.Инициализировать(...), но у внешней печатной формы определена только функция Печать(). Происходит исключение: Метод объекта не обнаружен (Инициализировать).Подобная ситуация усугубляется следующими факторами:
КаталогВременныхФайлов() возвращает единый для всех пользователей путь (например, C:\Windows\Temp).%USERPROFILE%\AppData\Local\Temp.Наиболее надежное решение — отказаться от статического имени PrnForm.tmp и перейти на генерацию уникальных имен файлов для каждого вызова. Для этого найдем в общем модуле УниверсальныеМеханизмы процедуры ОбработатьНажатиеНаДополнительнуюКнопкуЗаполненияТЧ и ПечатьПоДополнительнойКнопке.
Заменим жестко прописанное имя файла на вызов функции ПолучитьИмяВременногоФайла(). Посмотрим на пример доработки:
// Формируем уникальное имя файла для исключения коллизий
ИмяФайла = ПолучитьИмяВременногоФайла("epf");
Попытка
ДвоичныеДанныеОбработки.Записать(ИмяФайла);
Обработка = ВнешниеОбработки.Создать(ИмяФайла);
// Вызываем требуемую процедуру
Обработка.Инициализировать(ЭтотОбъект, СтрокаКнопки.Родитель.Имя, СтрокаКнопки.Родитель.Расшифровка);
// Обязательно удаляем временный файл с диска после использования
УдалитьФайлы(ИмяФайла);
Исключение
Попытка
УдалитьФайлы(ИмяФайла);
Исключение
КонецПопытки;
ОбщегоНазначения.СообщитьОбОшибке(ОписаниеОшибки(),, "Заполнение ТЧ не произведено!");
КонецПопытки;
При использовании уникального имени временного файла параллельные сеансы пользователей и разные потоки никогда не будут перезаписывать данные друг друга.
Если конфигурация находится на поддержке без возможности внесения изменений в код, необходимо проверить системные параметры операционной системы терминального сервера:
gpedit.msc).После применения этих политик каждый терминальный сеанс получит изолированную подпапку вида Temp\<SessionID>, что снизит вероятность взаимной перезаписи файлов между разными пользователями.
Если часто сбоит конкретная критически важная обработка заполнения, а править общие механизмы не планируется, целесообразно перенести алгоритм из внешнего файла непосредственно в дерево метаданных конфигурации в ветку Обработки. Обращение к встроенной обработке исключает дисковые операции с временными файлами и полностью устраняет ошибки файловой системы и блокировки со стороны стороннего ПО.