При работе в управляемом приложении (в частности, в 1С:ERP или других конфигурациях на платформе 1С:Предприятие 8.3) разработчики и пользователи нередко сталкиваются с исключением: «Использование синхронных методов на клиенте запрещено!». Ошибка часто проявляется при попытке загрузить внешние файлы (например, таблицы Excel при импорте экземпляров бюджета), подключить внешние компоненты или открыть диалоговые окна.
При этом поведение платформы может казаться непредсказуемым: процедура выполняется без сбоев в толстом клиенте или под учетной записью с полными правами, но падает с ошибкой в тонком клиенте под обычным пользователем или при запуске сеанса из конфигуратора. Разберем по шагам, почему возникает эта ошибка и какими способами ее можно устранить.
Проанализируем архитектурные особенности платформы 1С:Предприятие 8.3. В свойствах корневого элемента конфигурации присутствуют два ключевых параметра:
Не использовать).Не использовать).Когда данные режимы отключены, платформа запрещает вызывать на стороне клиента синхронные методы, которые блокируют интерфейсный поток (например, синхронные методы подключения внешних компонент, методы открытия модальных диалогов работы с файловой системой и вызовы COM-объектов).
Почему же ошибка часто выглядит как «плавающая» или зависящая от прав?
/EnableCheckModal и /EnableCheckExtensionsAndAddInsSyncCalls. Эти параметры принудительно включают строгий контроль синхронных вызовов независимо от фактических прав пользователя. При обычном пользовательском запуске без этих флагов платформа может временно пропускать синхронные вызовы, если компонента уже зарегистрирована в системе.%APPDATA%\1C\1Cv8\..., повторный синхронный метод установки не инициируется, и ошибка не проявляется. Если же входит другой пользователь или запуск происходит на чистом терминальном сервере, система пытается вызвать метод УстановитьВнешнююКомпоненту() или ПодключитьВнешнююКомпоненту(), что приводит к немедленной аварийной остановке.Рассмотрим основной и рекомендуемый фирмой «1С» способ устранения проблемы — адаптацию программного кода под стандарты разработки управляемого интерфейса.
Если в коде выполняется подключение внешней компоненты, заменим устаревший синхронный вызов на неблокирующий метод НачатьПодключениеВнешнейКомпоненты() с передачей обработчика через ОписаниеОповещения.
Посмотрим на пример правильной асинхронной инициализации компоненты на клиенте:
&НаКлиенте
Процедура ПодключитьКомпонентуДляЗагрузки()
Оповещение = Новый ОписаниеОповещения("ЗавершениеПодключенияКомпоненты", ЭтотОбъект);
НачатьПодключениеВнешнейКомпоненты(Оповещение, "ИмяКомпонентыВМакете");
КонецПроцедуры
&НаКлиенте
Процедура ЗавершениеПодключенияКомпоненты(Подключено, ДополнительныеПараметры) Экспорт
Если Подключено Тогда
// Продолжаем выполнение алгоритма импорта данных
ВыполнитьЗагрузкуФайла();
Иначе
ВызватьИсключение "Не удалось подключить внешнюю компоненту для обработки Excel!";
КонецЕсли;
КонецПроцедуры
Если ошибка возникает на этапе интерактивного выбора файла на диске, заменим синхронный метод ДиалогВыбораФайла.Выбрать() на асинхронный метод Показать():
&НаКлиенте
Процедура ВыбратьФайлExcel()
Диалог = Новый ДиалогВыбораФайлов(РежимДиалогаВыбораФайлов.Открытие);
Диалог.Заголовок = "Выберите файл Excel для импорта";
Диалог.Фильтр = "Файлы Excel (*.xlsx)|*.xlsx|Все файлы (*.*)|*.*";
Оповещение = Новый ОписаниеОповещения("ПослеВыбораФайла", ЭтотОбъект);
Диалог.Показать(Оповещение);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораФайла(ВыбранныеФайлы, ДополнительныеПараметры) Экспорт
Если ВыбранныеФайлы <> Неопределено И ВыбранныеФайлы.Количество() > 0 Тогда
ИмяВыбранногоФайла = ВыбранныеФайлы[0];
// Выполняем дальнейшую обработку выбранного файла
КонецЕсли;
КонецПроцедуры
Проанализируем альтернативный архитектурный подход. Наиболее стабильным решением при загрузке файлов в тонком клиенте является полный отказ от использования клиентских внешних компонент и COM-объектов (таких как Excel.Application).
Разберем по шагам правильную схему загрузки:
НачатьПомещениеФайлаНаСервер() или ПоместитьФайлНаСерверАсинх().ТабличныйДокумент или средств Библиотеки Стандартных Подсистем (БСП).Посмотрим на пример чтения листа Excel через ТабличныйДокумент на сервере:
&НаСервере
Процедура ПрочитатьДанныеИзХранилищаНаСервере(АдресВременногоХранилища)
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресВременногоХранилища);
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xlsx");
ДвоичныеДанные.Записать(ИмяВременногоФайла);
ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ИмяВременногоФайла, СпособЧтенияЗначений.Значение);
УдалитьФайлы(ИмяВременногоФайла);
// Выполняем обход строк таблицы и заполнение документа
Для НомерСтроки = 1 По ТабДок.ВысотаТаблицы Цикл
ЗначениеЯчейки = ТабДок.ПолучитьОбласть(НомерСтроки, 1).Текст;
// Обработка полученных значений
КонецЦикла;
КонецПроцедуры
Такой подход полностью исключает возникновение ошибок синхронных вызовов на клиенте, не зависит от разрядности установленного MS Office и корректно работает на любых операционных системах (включая Linux и веб-клиент).
Если конфигурация снята с поддержки и нет возможности оперативно переписать код импорта, рассмотрим вариант изменения настроек совместимости самой конфигурации:
Важно: этот способ является временным обходным путем. Для обеспечения стабильной работы и совместимости с будущими версиями платформы 1С:Предприятие рекомендуется выполнить полноценный рефакторинг с переходом на асинхронные методы или серверное чтение файлов.