Свободное ожидание 1с что это

Обновлено: 05.07.2024

Длительные операции на сервере

Область применения: управляемое приложение.

1. При разработке конфигураций следует избегать длительных вызовов из клиентского кода в серверный. Все длительные серверные вызовы, которые могут выполняться более 8 секунд в обычных сценариях работы пользователя, следует выполнять асинхронно, с помощью фонового задания.

К таким операциям относятся: формирование отчета, групповая обработка объектов, загрузка или выгрузка данных в другое приложение, заполнение больших табличных частей и т.п.

В противном случае такие вызовы могут привести к потере работоспособности приложения или затруднению работы с ним:

  • браузер может предложить прекратить длительно выполняющийся сценарий, после чего приложение станет неработоспособным;
  • веб сервер может прервать длительное обращение к серверу 1С:Предприятия и вернуть ошибку 504 (шлюз не отвечает);
  • в случае длительного выполнения операции, у пользователя нет возможности отменить ее.

2.1. Общий подход к асинхронному выполнению длительных серверных операций с помощью фонового задания:

    Код, выполняющий длительную обработку данных, располагается в модуле менеджера объекта* или в общем модуле. Результат своей работы он помещает во временное хранилище;


а для прочих мест – выводится блокирующая форма ( РежимОткрытияОкна = БлокироватьОкноВладельца ), на которой размещена декорация с анимированной картинкой и кнопка «Отмена» :

2.2. Асинхронное формирование отчета требуется только для тех отчетов, которые

  • разработаны без использования СКД или с использованием СКД, но с переопределенной процедурой формирования отчета (переопределен обработчик кнопки «Сформировать» или в обработчике модуля отчета ПриКомпоновкеРезультата устанавливается СтандартнаяОбработка = Ложь ).
  • и формирование которых, как правило, занимает длительное время.

Поведение таких отчетов должно быть максимально похожим на поведение отчетов на базе СКД, а именно:

  • форму отчета не следует блокировать на время его формирования;
  • пользователь может изменить настройки и переформировать отчет, не дожидаясь окончания его формирования;
  • при закрытии формы отчета, формирование отчета прерывается.

3. При использовании в конфигурации Библиотеки стандартных подсистем в распоряжении разработчика имеются вспомогательные функции и процедуры общих модулей ДлительныеОперации , ДлительныеОперацииКлиент , а также процедура УстановитьСостояниеПоляТабличногоДокумента общего модуля ОбщегоНазначенияКлиентСервер .

Пример выполнения функции в фоновом задании при использовании в конфигурации Библиотеки стандартных подсистем. В модуле менеджера объекта размещена функция, которая выполняет поиск настроек и возвращает их:

Функция ОпределитьНастройкиУчетнойЗаписи(АдресЭлектроннойПочты, Пароль) Экспорт
.
Возврат Настройки;
КонецФункции

В форме объекта выполняется вызов этой функции в фоновом задании в три этапа:
1) запуск фонового задания на сервере,
2) подключение обработчика завершения фонового задания на клиенте,
3) обработка результата выполнения фонового задания.

&НаКлиенте
Процедура НастроитьПараметрыПодключенияАвтоматически()
// 1. Запуск фонового задания на сервере.
ДлительнаяОперация = НачатьПоискНастроекУчетнойЗаписи();

// 2. Подключение обработчика завершения фонового задания.
ПараметрыОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
Оповещение = Новый ОписаниеОповещения("ПриЗавершенииПоискаНастроек", ЭтотОбъект);
ДлительныеОперацииКлиент.ОжидатьЗавершение(ДлительнаяОперация, Оповещение, ПараметрыОжидания);
КонецПроцедуры

&НаСервере
Функция НачатьПоискНастроекУчетнойЗаписи()
ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияФункции(УникальныйИдентификатор);
Возврат ДлительныеОперации.ВыполнитьФункцию(ПараметрыВыполнения, "Справочники.УчетныеЗаписиЭлектроннойПочты.ОпределитьНастройкиУчетнойЗаписи",
АдресЭлектроннойПочты, Пароль);
КонецФункции

// 3. Обработка результата выполнения фонового задания.
&НаКлиенте
Процедура ПриЗавершенииПоискаНастроек(Результат, ДополнительныеПараметры) Экспорт

Если Результат = Неопределено Тогда // Пользователь отменил задание.
Возврат;
КонецЕсли;

Если Результат.Статус = "Ошибка" Тогда
ВызватьИсключение Результат.КраткоеПредставлениеОшибки;
КонецЕсли;

Настройки = ПолучитьИзВременногоХранилища(Результат.АдресРезультата);
УдалитьИзВременногоХранилища(Результат.АдресРезультата);
УстановитьНастройкиУчетнойЗаписи(Настройки);

Методическая рекомендация (полезный совет)

3.1. При каждом выполнении фонового задания его результат помещается во временное хранилище на время жизни формы:

ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияФункции(УникальныйИдентификатор);
ДлительныеОперации.ВыполнитьФункцию(ПараметрыВыполнения, ПараметрФоновогоЗадания);

Если длительная операция выполняется пользователем многократно, пока эта форма открыта, то временные хранилища накапливаются, что вызывает рост потребления памяти. Поэтому для уменьшения расхода оперативной памяти в большинстве случаев рекомендуется очищать временное хранилище сразу после получения результата фонового задания:

Настройки = ПолучитьИзВременногоХранилища(Результат.АдресРезультата);
УдалитьИзВременногоХранилища(Результат.АдресРезультата); // Данные во временном хранилище больше не требуются.

Если же результат фонового задания требуется сохранять на протяжении нескольких серверных вызовов, то необходимо передавать фиксированный адрес заранее инициализированного временного хранилища:

&НаСервере
Процедура ПриСозданииНаСервере(Отказ)
АдресРезультатаФоновогоЗадания = ПоместитьВоВременноеХранилище(Неопределено, УникальныйИдентификатор); // Резервируем адрес временного хранилища
КонецПроцедуры

&НаСервере
Функция НачатьПоискНастроекУчетнойЗаписи()
ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияФункции(УникальныйИдентификатор);
ПараметрыВыполнения.АдресРезультата = АдресРезультатаФоновогоЗадания; // всегда используем одно и то же временное хранилище

Возврат ДлительныеОперации.ВыполнитьФункцию(ПараметрыВыполнения,
"Справочники.УчетныеЗаписиЭлектроннойПочты.ОпределитьНастройкиУчетнойЗаписи",
АдресЭлектроннойПочты, Пароль);
КонецФункции

4. Если в конфигурации реализуются алгоритмы, инициирующие запуск фоновых заданий или запись данных информационной базы без участия пользователя (например, регулярное обновление информации в открытой форме), то в них следует проверять, что в текущем сеансе не установлен монопольный режим. В противном случае, следует блокировать попытки выполнения таких действий. Например:

Если МонопольныйРежим() Тогда
Возврат;
КонецЕсли;

5. В некоторых случаях возникает необходимость в выполнении длительных операций, требующих установки монопольного режима доступа к информационной базе. Например:

Обновление данных ИБ при первом интерактивном запуске программы после обновления конфигурации; Выгрузка данных информационной базы в файл для перехода в сервис; Использования монопольного режима для снижения времени выполнения массовых операций по изменению данных;

При этом необходимо сначала устанавливать монопольный режим, а затем выполнять запуск фонового задания, которое реализует саму длительную операцию. В этом случае фоновым заданием будет унаследован монопольный режим, ранее установленный из пользовательского сеанса (см. документацию к платформе).

На время выполнения этого фонового задания следует блокировать весь интерфейс приложения, открывая форму ожидания завершения операции в режиме РежимОткрытияОкна = БлокироватьВесьИнтерфейс. Блокировать интерфейс приложения требуется потому, что на время выполнения задания полноценная работа пользователя с приложением уже невозможна:

  • Если пользователь(*) попытается записать какой-либо объект, это приведет к ошибке (из-за установленного монопольного режима);
  • В ряде случаев могут запускаться фоновые задания в качестве реакции на действия пользователя случае (при поиске в динамическом списке, при вводе по строке, формировании отчетов и пр.), которые также завершатся с ошибкой.
    Кроме того, на самой форме ожидания длительной операции не следует размещать элементы управления, которые могут приводить к запуску таких фоновых заданий. Например: поля ввода, динамические списки и отчеты.

* Примечание: ошибки записи также возникают в тех случаях, когда объекты записываются программно, например, из обработчиков ожидания. В них также следует проверять монопольный режим согласно п.5.

Механизм подключения обработчика ожидания известен с 8.0, описан в Синтакс-помощнике и десятках публикаций. По сути, это механизм, реализующий псевдо-параллельный вызов процедур клиентского контекста сеанса с заданной периодичностью либо однократно.

С точки зрения языка 1С, это две процедуры глобального контекста сеанса: ПодключитьОбработчикОжидания и ОтключитьОбработчикОжидания. Пересказывать хелп не будем, отметим только, что сложился стереотип, будто однократность применима лишь для таймаута менее 1 секунды; но реально однократный вызов может использовать любой таймаут.

С точки зрения платформы, это поддерживаемая процессом rphost, единая для сеанса, виртуальная таблица ключей, таймаутов и текущих значений таймера.
* Ключ - хеш от ID модуля, откуда был выполнен вызов, ID модуля вызываемой процедуры обработчика, и имени процедуры обработчика. Идентификаторы модулей можно увидеть, выгрузив конфигурацию в файлы.
* Таймаут - число, рассчитывается в миллисекундах.
* Текущее значение таймера - момент предыдущего срабатывания, дата/время с миллисекундами. Таймеры отталкиваются от текущей даты/времени сеанса в момент компиляции подключения обработчика или реинициализации таблицы.

Эта таблица обслуживается специальным обработчиком, который не является сервисом кластера, а просто часть механизма платформы. Обработчик не учитывает успешность вызова и выполнения вызываемой процедуры.

Эта таблица не относится к сеансовым данным (косвенно упоминается в руководствах лишь как "прочие данные сеанса"), при обращениях к серверу и ряде других операций значения таймеров сбрасываются, и очередной вызов происходит гораздо раньше, чем истёк таймаут.

Реинициализация этой таблицы происходит при любом "возврате на клиент", т.е. при передаче менеджером кластера управления клиенту (штатного, по службе кластера, или по исключению) и передаче хранимых для рабочего процесса сеансовых данных. Штатно - понятно; по службе кластера - имеется в виду служба отладчика, т.е. продолжение действия по прохождении точки останова; по исключению - только если ошибка была восстановимая, касалась сервера либо обмена клиент-сервер и (если запуск был из формы) не касалась блокировок этой формы.

Прекращение обработки конкретной записи этой таблицы происходит, когда из стека исчезает указатель в памяти на область, хранящую тот контекст (форму/модуль и их кэш), откуда выполнялось подключение обработчика (а вовсе не тот контекст, где располагается вызываемая по таймауту процедура, как иногда ошибочно пишут). Грубо говоря для большинства случаев, обработчик стопится, когда закрывается форма или приложение, откуда он стартовал.

Существенно различно в разных релизах до 8.3.11 ведёт себя при остановке на точке останова; в текущих релизах всегда сбрасываются таймауты и сразу стартует обработка заново - и по прохождении останова, и при остановке по ошибке, если ошибка была обработана. Не важно, где находится точка останова - в действиях, вызванных обработчиком, или в других действиях, реинициализация делается всегда.

Поведение аналогично и для файловых, и для клиент-серверных ИБ. Поведение в клиенте тестирования аналогично поведению в обычных запусках клиента. Поведение в веб-клиенте формально одинаковое, но известны случаи, когда в браузере "Safari" таймауты "сжимались" относительно ожидаемого в состоянии "покоя" клиента, т.е. написано было 60, а реально срабатывало через 45-48 секунд.

Сеансы и обработчики. До версии 8.3.7.2008 наличие хотя бы одного сработавшего обработчика ожидания вынуждало сеанс никогда не "засыпать" и даже не считаться пассивным. В некоторых релизах 8.3.9 и 8.3.11 запущенные обработчики не мешали сеансу засыпать и быть впоследствии удалённым, но продолжали работать, что проверено выполнением записи из их процедуры в клиентский файл на локальном ПК (занята ли бывала при этом лицензия, сведений нет) - фиксировать активность сеанса средствами ЖР нельзя было потому, что запись в ЖР это обращение к сервису кластера и вообще к серверу.

Наличие назначенного сеансу соединения никак ни на что не влияло и не влияет. Соединение может пропасть, а обработчик продолжит свою работу.

В настоящее время запущенные обработчики в понятие "активность пользователя" (не юзера-за-экраном, а именно пользователя в админском смысле) не входят. Сведений о том, передаётся ли прежняя сохранённая таблица обработчиков сеансу кластером при возобновлении его работы, или просто реинициализируется, нет.

Из устройства этого механизма следует ряд нюансов.

1. Обработчик можно запускать и останавливать в форме, экземпляр которой создан, но не открыт; в любой момент, пока её контекст есть в некоей переменной. Запускать и останавливать придётся отдельными экспортными процедурами, т.к. обращение "НеоткрытаяФорма.ПодключитьОбработчикОжидания" игнорируется без генерации исключения. С уничтожением переменной формы останавливается и обработчик - поэтому следует быть внимательными, чтобы после закрытия запустившей формы или команды не случилось зависания этой переменной в памяти сеанса.


2. Не-клиентские и не-контекстные процедуры не могут обрабатываться. Логично - в таблице тайминга ориентируемся на хеш, связанный с контекстом. Процедура не должна иметь даже необязательные параметры, и быть экспортной. Также, может быть подключена функция; результат её выполнения игнорируется.

3. В качестве запускаемых обработчиком могут быть процедуры модуля приложения, любого глобального общего модуля, для которого указано исполнение на клиенте (в т.ч. наряду с исполнением на сервере или во внешнем соединении). Если модуль не "чисто" клиентский, по умолчанию директивы компиляции и инструкции препроцессора исполняемой процедуре всё равно не нужны - при наличии флага "Клиент" для модуля обработчик ожидания все его "подходящие" процедуры считает клиентскими. Но, конечно, желательно всё указывать в явном виде. Важно! Запуск и остановка всегда должны находиться в контексте одного модуля, иначе запустить - запустит, но потом не остановит. Это могут быть модуль приложения, глобальные и неглобальные общие модули, модули объектов и модули менеджеров - главное, чтобы вызов старта и остановки происходил в одном модуле.
В модуле приложения подключение можно выполнять в любом системном событии - в ПередНачаломРаботыСистемы оно уже корректно запустится, а в событиях завершения работы системы будет проигнорировано.

5. Сколько бы раз ни было запущено подключение обработчика некоей процедуры, учитывается лишь последний запуск - он "перебивает" предыдущие. Повторное/многократное отключение обработчика игнорируется без генерации исключения. В том числе и если обработчик вообще не был запущен.


6. Из процедуры, вызванной обработчиком, можно повторно подключать, переподключать с иным таймаутом, останавливать этот обработчик. Например, можно эмулировать однократный запуск - допустим, условие определяется при срабатывании; можно эмулировать многократный запуск-вызов с таймаутом менее 1 секунды. В этом случае, т.е. если внутри процедуры-обработчика однократного таймаута находится повторное её же подключение, получается практически мгновенный и при необходимости бесконечный самовызов. Зависаний и торможений, если в рабочей части вызванного нет "тяжёлых" действий, не замечено.


7. При одинаковом таймауте, обработчики модуля приложения и глобальных модулей более приоритетны при опросе и срабатывании, чем обработчики форм. Между собой обработчики модуля приложения и глобальных модулей "равноправны", формы между собой - тоже. Это означает, что и для однократного, и для постоянного вызова всегда сначала отрабатывает "глобальный", потом "форменный". Независимо от порядка подключения обработчиков, если они были подключены за одну компиляцию фрагмента кода (это хорошо заметно на примере однократных вызовов с таймаутом 0.1). А вот при равных "правах" вызовы отрабатывают по порядку инициализации-подключения их обработчиков.

8. Таймауты, имеющие дробные значения секунд, корректно обрабатываются независимо от значения флага однократности (это легко проверить с помощью ТекущаяУниверсальнаяДатаВМиллисекундах), с точностью до десятых.

9. В синтакс-помощнике указано, что "вызов будет осуществляться только в "состоянии покоя", то есть в тот момент, когда программа не выполняет никаких действий.". Наличие на экране другой формы или модального диалога в общем случае тоже не есть выполнение действия, однако, поведение различно. Обработчик НЕ "тормозят" ни модальные, ни асинхронно-псевдомодальные служебные или платформенные диалоги. Обработчик "тормозят" открытые формы, чей режим открытия окна "Блокировать весь интерфейс". По завершении действий с ними обработка возобновляется, и тайминг не сбивается. Обработчик НЕ тормозят и не сбивают тайминг все остальные разнообразно открытые формы с прочими режимами, даже если форма, где запущен обработчик - их владелец, и для них указано "Блокировать окно владельца".

10. Редко, но используется запуск средствами СОМ полноценного приложения V83.Application. При таком запуске расположенные в модуле приложения обработчики запускаются и живут до конца сеанса, независимо от видимости приложения. Возможен запуск КомОбъект.ПодключитьОбработчикОжидания (справедливо и для модуля приложения, и для форм, хотя в этом случае работа с формами уже совсем фантастика) и остановка аналогично. Важно, что в этом случае при закрытии запускавшего контекста (и формы, и самого запустившего сеанса) запущенный продолжает работать, что при Visible=Ложь кончится снятием через диспетчер задач. В некоторых релизах сеанс, применительно к ком-объекту которого делали вызов, при закрытии приложения выдаёт невосстановимую ошибку.

p.s. Сведения о ёмкости служебной таблицы запущенных обработчиков найти не удалось, т.е. сколько максимум может быть таких обработчиков в сеансе, или в конкретном контексте, данных нет. Эксперимент со 100 разными процедурами с одним или разными таймаутами показал правильную штатную работу.


Я наверняка многое упустил; дополнения и замечания приветствуются.

Обработчик ожидания – выполнение кода через заданное время


В этой статье покажем как в 1С выполнять код с заданной периодичностью с использованием функций обработчика ожидания:

  • ПодключитьОбработчикОжидания
  • ОтключитьОбработчикОжидания

Обработчик ожидания – это механизм, который используется на стороне клиентского приложения (т.е. в пользовательских формах и т.п.). Его задача запустить процесс, который выполнит определённые действия однократно или через заданный интервал времени. Обработчик ожидания выполняет свои действия параллельно (в выделенном потоке) основной работе пользователя.

Синтаксис

Рассмотрим синтаксис вышеуказанных функций:

ПодключитьОбработчикОжидания(<ИмяПроцедуры>, <Интервал>, <Однократно>) – Подключает вызов указанной процедуры 1С через определённый интервал времени.

ОтключитьОбработчикОжидания(<ИмяПроцедуры>) – Отключает вызов процедуры, которая была подключена ранее с помощью ПодключитьОбработчикОжидания.

Вызов обработчика ожидания продолжается до тех пор, пока пользовательская форма не будет закрыта или пока не будет вызвана процедура ОтключитьОбработчикОжидания.

Обработчик ожидания доступен только на клиенте. Чтобы вызвать серверную функцию, необходимо обратиться к ней из клиентского окружения.

Пример вызова обработчика ожидания

Приведём пример работы с обработчиком ожидания:

&НаКлиенте Процедура ПодключитьОбработчик() ПодключитьОбработчикОжидания("ОбработатьОжидание", 60, Ложь); КонецПроцедуры &НаКлиенте Процедура ОбработатьОжидание() ОбработатьОжиданиеНаСервере(); КонецПроцедуры &НаСервере Процедура ОбработатьОжиданиеНаСервере() //Выполняем серверный код 1С КонецПроцедуры;

В этом примере обработчик вызывается с клиента и выполняет клиентскую процедуру, которая, в свою очередь, передаёт управление серверной процедуре.

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

Программа 1С постоянно усовершенствуется, добавляются новые функции, позволяющие сделать работу в системе более удобной.

Событие в программе 1С возникает в тот момент, когда пользователь использует какую-либо кнопку, в результате нажатия на которую открывается форма или записывается документ.

Функции программы позволяют выполнять определённые действия в результате возникновения определённого события. Для этого необходимо прописать подробные условия во встроенной программе. Для этого программисту необходимо назначить обработчик на каждое событие.

Кроме того, программист может настроить систему таким образом, что обработчик будет назначен сразу на несколько документов при нажатии на одну кнопку.

Чтобы найти элемент дерева конфигурации «Подписки на события», достаточно открыть вкладку «Общие» в дереве конфигурации. В выпадающем списке дерева можно выбрать необходимый пункт.


В самой подписке на события выбирается источник, который будет основой для осуществления определённых событий.

Функция-обработчик выбирается в общем модуле в дереве конфигурации.

Как проверить заполнение поля?

Например, для работы в системе программист добавил общий реквизит. Необходимо проконтролировать заполнение данного поля в каждом вновь созданном документе. Для выполнения этого действия следует учитывать несколько этапов.

Пользователю необходимо добавить в систему новую подписку, следует придумать для неё новое название и написать его. В свойствах подписки на событие устанавливаются ссылки на документы, на которые впоследствии будет установлен обработчик.


Следующий шаг – выбор в свойствах одного из вариантов событий, которые будут происходить после нажатия кнопок с документами или справочниками.



Работа с формами 1С

Как показывает практика, можно значительно упростить работу со многими объектами в 1С. Чаще всего это документы и справочники. Однако на данный момент невозможно подписаться на события 1С формы, например, при её открытии.

Следует понимать, что возможность использования событий напрямую зависит от используемого объекта. Однако, если выбрать сразу несколько объектов, в итоге в списке будут только те события, которые возможно применить к каждому из объектов.

Функция-обработчик

Следующий этап – работа с функцией обработчиком события. Для её использования необходимо установить серверный общий модуль. Эти настройки можно изменить во вкладке «Свойства». Функция-обработчик создаётся после нажатия кнопки «Лупа».



Для чего нужна функция подписки на события?

За несколько этапов пользователь сам может установить функцию подписки на событие в 1С. Этот приём позволяет выполнять определённую функцию при записи любого документа или создания нового.

Создание подписки значительно упрощает работу в программе 1С, а также экономит время пользователю.

Читайте также: