Два независимых собственных опыта на последовательной карте: реальная задача порождается Старт, однопараметровый обработчик проверяет готовность, состояние задачи и процесса читается после метода; каждая транзакция отменяется.
Где и как запускать
Полный модуль обычной формы ЗапускВыполнения85 в толстом клиенте Windows, режим ОбычноеПриложение, новый стенд УчебноеВыполнениеЗадачи85.
Подготовка
Создайте новую пустую конфигурацию УчебноеВыполнениеЗадачи85 на платформе8.5.1.1343. Рабочие базы, существующие процессы и ручные пользовательские ссылки не подходят.
Основной режим запуска — Обычное приложение; толстый клиент Windows именно в ОбычноеПриложение. Управляемый режим не вызывает ПередИнтерактивнымВыполнением и отклоняется кодом.
Задачи → УчебнаяЗадача85: номер Строка9, автонумерация, Наименование100, реквизит ГотоваКВыполнению85 типа Булево исходно Ложь. Не добавляйте адресацию или обязательные поля.
Бизнес-процессы → УчебныйПроцесс85: номер Строка9, автонумерация, Маркер85 Строка36; Задача=УчебнаяЗадача85.
Карта процесса строго Старт → одна одиночная точка действия Опыт85 → Финиш. Представление действия «Собственный опыт выполнения»; нет условий, групповых точек, подпроцессов и адресации.
В модуль задачи вставьте целиком отдельный ПередИнтерактивнымВыполнением из карточки. Модуль процесса и обработчики точек маршрута пустые; никаких подписок, обмена и внешних действий.
Не копируйте ПередЗаписью с безусловным отказом из урока просмотра: этот новый стенд действительно записывает свои данные внутри отменяемых транзакций.
Обработки → ЗапускВыполнения85 → обычная форма Форма. Весь основной код находится в её модуле без клиент-серверных директив и без общего модуля.
Реквизиты формы: ПодтверждаюПустойСтенд85 и Занято85 типа Булево, Итог85 Строка неограниченной длины; исходные флажки Ложь, занятость и итог только для просмотра.
Обычная кнопка ПроверитьСвоёВыполнение85: Нажатие=ПроверитьСвоёВыполнение85. Это обработчик Кнопка, не команда управляемой формы.
Нажмите F7 и обновите только свой пустой стенд. runtimeVerifiedScenarios=0: 1С, маршрут, запись, интерактивное выполнение и откат здесь не запускались.
Один свой пользователь, один клиент, без фоновых заданий, других писателей, сеансов и сетевых/почтовых/печатных действий. Откат базы не отменяет произвольные внешние эффекты.
Подтвердите пустой стенд и вручную запустите команду. Два опыта используют разные собственные процессы, UUID и маркеры; готовность берётся только из литералов Ложь и Истина основного кода.
Процесс записывается и порождает задачу Старт внутри своей транзакции. Задача находится параметризованным запросом только по этому процессу, а не создаётся вручную для имитации маршрута.
Первый опыт требует штатного отказа и незавершённого процесса. Если метод при отказе возвращает исключение, выполняется откат и сообщается исключение, а не ложный успешный отказ.
Второй опыт разрешает выполнение и требует реально прочитанных Выполнена=Истина и Завершен=Истина. Затем оба созданных объекта исчезают после отмены своей транзакции.
Процедура ПроверитьСвоёВыполнение85(Кнопка)
Если Не ПодтверждаюПустойСтенд85 Тогда
ВызватьИсключение "Только собственный пустой стенд УчебноеВыполнениеЗадачи85 с согласием";
КонецЕсли;
Если ТекущийРежимЗапуска() <> РежимЗапускаКлиентскогоПриложения.ОбычноеПриложение Тогда
ВызватьИсключение "Нужно обычное приложение, не управляемое";
КонецЕсли;
Если Занято85 Или ТранзакцияАктивна() Тогда
ВызватьИсключение "Нельзя повторять опыт или использовать чужую транзакцию";
КонецЕсли;
ВыборкаПроцессов = БизнесПроцессы.УчебныйПроцесс85.Выбрать();
ВыборкаЗадач = Задачи.УчебнаяЗадача85.Выбрать();
Если ВыборкаПроцессов.Следующий() Или ВыборкаЗадач.Следующий() Тогда
ВызватьИсключение "Оба учебных вида должны быть пустыми; чужие записи не используются";
КонецЕсли;
Занято85 = Истина;
Попытка
Отказ = ВыполнитьСвойМаршрут85(Ложь);
Успех = ВыполнитьСвойМаршрут85(Истина);
Итог85 = Отказ + " " + Успех;
Исключение
Занято85 = Ложь;
Итог85 = ОписаниеОшибки();
ВызватьИсключение;
КонецПопытки;
Занято85 = Ложь;
КонецПроцедуры
Функция ВыполнитьСвойМаршрут85(Готовность)
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Каждый собственный опыт начинает отдельную транзакцию";
КонецЕсли;
Маркер = Строка(Новый УникальныйИдентификатор);
СсылкаПроцесса = БизнесПроцессы.УчебныйПроцесс85.ПолучитьСсылку(Новый УникальныйИдентификатор);
Если СсылкаПроцесса.ПолучитьОбъект() <> Неопределено Тогда
ВызватьИсключение "Плановая ссылка занята; чужой процесс не используем";
КонецЕсли;
СсылкаЗадачи = Неопределено;
ОшибкаОтказа = "";
НачатьТранзакцию();
Попытка
Процесс = БизнесПроцессы.УчебныйПроцесс85.СоздатьБизнесПроцесс();
Процесс.УстановитьСсылкуНового(СсылкаПроцесса);
Процесс.Дата = ТекущаяДата();
Процесс.Маркер85 = Маркер;
Процесс.Записать();
Процесс.Старт(БизнесПроцессы.УчебныйПроцесс85.ТочкиМаршрута.Старт);
Процесс.Прочитать();
Если Не Процесс.Стартован Или Процесс.Завершен Тогда
ВызватьИсключение "Свой процесс не ожидает единственную задачу действия";
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ЗадачиОпыта.Ссылка КАК Ссылка
|ИЗ Задача.УчебнаяЗадача85 КАК ЗадачиОпыта
|ГДЕ ЗадачиОпыта.БизнесПроцесс = &СвойПроцесс";
Запрос.УстановитьПараметр("СвойПроцесс", СсылкаПроцесса);
Найденные = Запрос.Выполнить().Выгрузить();
Если Найденные.Количество() <> 1 Тогда
ВызватьИсключение "Нужна ровно одна реальная задача собственного одиночного действия";
КонецЕсли;
СсылкаЗадачи = Найденные.Получить(0).Ссылка;
Задача = СсылкаЗадачи.ПолучитьОбъект();
Если Задача = Неопределено Тогда
ВызватьИсключение "Реальная порождённая задача не найдена";
КонецЕсли;
Если Задача.БизнесПроцесс <> СсылкаПроцесса Или Задача.Выполнена
Или Задача.ТочкаМаршрута <> БизнесПроцессы.УчебныйПроцесс85.ТочкиМаршрута.Опыт85 Тогда
ВызватьИсключение "Нельзя выполнять задачу чужого процесса или другой точки";
КонецЕсли;
Задача.ГотоваКВыполнению85 = Готовность;
Задача.Записать();
Задача.ДополнительныеСвойства.Вставить("МаркерОпыта85", Маркер);
Задача.ДополнительныеСвойства.Вставить("ОбработчикВызван85", Ложь);
Задача.ДополнительныеСвойства.Вставить("ОтказОбработчика85", Неопределено);
Попытка
Задача.ВыполнитьЗадачуИнтерактивно();
Исключение
Если Готовность Тогда
ВызватьИсключение;
КонецЕсли;
ОшибкаОтказа = ОписаниеОшибки();
КонецПопытки;
Вызван = Неопределено;
ОтказОбработчика = Неопределено;
Если Не Задача.ДополнительныеСвойства.Свойство("ОбработчикВызван85", Вызван)
Или Не Задача.ДополнительныеСвойства.Свойство("ОтказОбработчика85", ОтказОбработчика) Тогда
ВызватьИсключение "Вызов собственного интерактивного обработчика не подтвердился";
КонецЕсли;
Если Вызван <> Истина Или ОтказОбработчика <> (Не Готовность) Тогда
ВызватьИсключение "Нужен именно ожидаемый отказ или разрешение собственного обработчика";
КонецЕсли;
Если ОшибкаОтказа = "" Тогда
Задача.Прочитать();
Процесс.Прочитать();
Если Задача.Выполнена <> Готовность Или Процесс.Завершен <> Готовность Тогда
ВызватьИсключение "Реальные сохранённые состояния задачи и процесса не совпали с ожидаемым результатом";
КонецЕсли;
КонецЕсли;
Если ТранзакцияАктивна() Тогда
ОтменитьТранзакцию();
КонецЕсли;
Исключение
Если ТранзакцияАктивна() Тогда
ОтменитьТранзакцию();
КонецЕсли;
ВызватьИсключение;
КонецПопытки;
Если ТранзакцияАктивна() Или СсылкаПроцесса.ПолучитьОбъект() <> Неопределено Тогда
ВызватьИсключение "Собственный процесс остался после отката";
КонецЕсли;
Если СсылкаЗадачи = Неопределено Тогда
ВызватьИсключение "Опыт не получил реальную собственную задачу";
КонецЕсли;
Если СсылкаЗадачи.ПолучитьОбъект() <> Неопределено Тогда
ВызватьИсключение "Собственная задача осталась после отката";
КонецЕсли;
Если Готовность Тогда
Возврат "Разрешённый опыт: собственная задача выполнена и свой процесс завершён внутри транзакции; обе записи отменены.";
КонецЕсли;
Если ОшибкаОтказа <> "" Тогда
ВызватьИсключение "Обработчик подтвердил отказ, но метод завершился исключением; опыт отменён и не считается штатным отказом: " + ОшибкаОтказа;
КонецЕсли;
Возврат "Запрещённый опыт: обработчик отказал, задача не выполнена и свой процесс не завершён; обе записи отменены.";
КонецФункцииПередИнтерактивнымВыполнением УчебнаяЗадача85
УчебноеВыполнениеЗадачи85 → Задачи → УчебнаяЗадача85 → Модуль объекта
Полный модуль собственной задачи: единственный однопараметровый обработчик отказа или разрешения, без внешних действий.
Процедура ПередИнтерактивнымВыполнением(Отказ)
Если ТекущийРежимЗапуска() <> РежимЗапускаКлиентскогоПриложения.ОбычноеПриложение Тогда
ВызватьИсключение "Нужен собственный стенд УчебноеВыполнениеЗадачи85 в обычном приложении";
КонецЕсли;
Маркер = Неопределено;
Если Не ЭтотОбъект.ДополнительныеСвойства.Свойство("МаркерОпыта85", Маркер) Тогда
ВызватьИсключение "Нет контекста собственного выполнения";
КонецЕсли;
Если ЭтотОбъект.БизнесПроцесс.Пустая() Тогда
ВызватьИсключение "Нужна задача, реально порождённая собственным маршрутом";
КонецЕсли;
Процесс = ЭтотОбъект.БизнесПроцесс.ПолучитьОбъект();
Если Процесс = Неопределено Тогда
ВызватьИсключение "Собственный процесс не найден";
КонецЕсли;
Если Процесс.Маркер85 <> Маркер Или Не Процесс.Стартован Или Процесс.Завершен Тогда
ВызватьИсключение "Задача не относится к своему ожидающему процессу";
КонецЕсли;
ЭтотОбъект.ДополнительныеСвойства.Вставить("ОбработчикВызван85", Истина);
Отказ = Не ЭтотОбъект.ГотоваКВыполнению85;
ЭтотОбъект.ДополнительныеСвойства.Вставить("ОтказОбработчика85", Отказ);
КонецПроцедурыРазбор по шагам
Проверяются стенд, версия, согласие, обычный режим, отсутствие внешней транзакции и пустота обоих видов. Флаг занятости защищает от повторной кнопки той же формы.
Каждый вызов helper создаёт собственный процесс с новым плановым UUID и маркером. Реальный Старт проходит до единственного действия и порождает одну задачу маршрута.
Параметризованный запрос находит задачу только собственного процесса. Проверяются количество1, наличие объекта, принадлежность процессу, невыполненное состояние и конкретная точка Опыт85.
В первом опыте ГотоваКВыполнению85=Ложь, во втором Истина. Собственный контекст задаётся перед методом; обработчик проверяет сохранённый процесс и записывает только доказательство вызова в ДополнительныеСвойства.
ПередИнтерактивнымВыполнением имеет один возвращаемый Отказ и вызывается самим API. Оно отказывает неготовой задаче и разрешает готовую; readonly-флаги выполнения и завершения не присваиваются.
ВыполнитьЗадачуИнтерактивно вызывается на реальной задаче маршрута. При штатном возврате Прочитать получает реальные значения задачи и процесса: оба должны соответствовать готовности.
Если метод завершился исключением, данные не читаются повторно внутри потенциально нарушенной транзакции. Сначала отменяется собственный опыт; даже подтверждённый отказ не скрывает исключение.
Каждая собственная транзакция отменяется при нормальном или ошибочном пути. Вне неё отдельно проверяется отсутствие процесса и порождённой задачи по полученным реальным ссылкам.
Итог содержит штатный отказ первого опыта и штатное выполнение второго только после всех проверок. Занятость снимается до передачи исключения пользователю.
Как проверить результат
ПередИнтерактивнымВыполнением действительно оставляет свой маркер вызова и правильный Отказ, не просто сравнивается флажок готовности в основном модуле.
Первый штатный опыт: задача не выполнена, процесс не завершён. Второй: задача выполнена методом, процесс завершён уведомлением маршрута.
В обоих случаях задача появилась от реального Старт и относится к единственному собственному процессу и точке Опыт85.
После каждого опыта транзакция закрыта, процесс и его задача отсутствуют по собственным ссылкам. Никаких ЗафиксироватьТранзакцию или непосредственного Удалить нет.
Любое неожиданное исключение, отсутствие callback или другое состояние приводит к ошибке после отката, а не к успешному учебному отчёту.
Ожидаемый результат
При будущем собственном ручном штатном запуске отдельно подтверждены отказ и успешное интерактивное выполнение настоящей задачи своего маршрута; оба независимых опыта полностью отменены.
На что обратить внимание
Этот метод доступен в толстом клиенте. ПередИнтерактивнымВыполнением не вызывается в УправляемоеПриложение, поэтому выбран и проверяется обычный режим.
Не применяйте метод к произвольной вручную созданной несвязанной задаче. Здесь принадлежность реальному собственному процессу и точке маршрута проверяется перед выполнением.
Выполнение метода записывает задачу и уведомляет породивший её процесс. Присваивание Выполнена или Завершен не воспроизводит эти действия и здесь не используется.
Готовность — собственный изменяемый реквизит учебного объекта, не readonly-флаг исполнения. Он задаёт бизнес-условие отказа и не заменяет результат метода.
ДополнительныеСвойства хранит доказательство вызова только в текущем экземпляре языка. Оно проверяется до Прочитать; после отката этот экземпляр больше не используется.
Отказ и исключение метода — разные исходы. Если метод завершился исключением, урок не объявляет штатный отказ и не продолжает второй опыт как будто всё прошло нормально.
Два опыта не изменяют один и тот же уже откатившийся экземпляр. Для каждого создаются новые процесс, задача маршрута и собственные ссылки.
Это демонстрация одного действия без адресации и конкурирующих исполнителей. Стандартный выбор всех задач текущего пользователя и контроль производственных прав здесь не реализованы.
Запрос ограничен собственной ссылкой, но отдельная пустая база и единственный писатель всё равно обязательны. Маркер и UUID не делают код production-службой массового выполнения задач.
Своя транзакция завершается только ОтменитьТранзакцию. Откат базы не отменяет внешнюю сеть, почту, печать и файлы из произвольных обработчиков; нельзя отменять чужую транзакцию.
Внешние действия и подписки должны отсутствовать. Этот учебный маршрут не запускает настоящие рабочие роботы, фоновые задания или интеграции.
Откат записи базы не возвращает объекты языка в начальное состояние. Проверка отсутствия идёт по ссылкам после отката, а не по прежним значениям в памяти.
Формы задачи не открываются и пользователь не редактирует записи в середине транзакции. Модальных вопросов, удерживающих транзакцию на время ответа, в приведённом коде нет.
Если авария оборвала работу, штатный результат не гарантируется. Ручные тесты требуют отдельного разрешения; runtimeVerifiedScenarios=0, фактических действий в1С здесь нет.
Новых резервных копий и архивов справочника нет. Этот код только написан и статически проверяется; операции маршрута и выполнения реально не выполнялись.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.