Выполнить тот же двоичный конвейер через оповещения

Учебные задачи

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

Где и как запускать

Модуль пустой управляемой формы учебной внешней обработки; тонкий или толстый клиент Windows. Вставьте весь модуль. Это не серверный код.

Подготовка

  1. Создайте учебную внешнюю обработку с пустой управляемой основной формой. Создайте команду УчебныйПример и кнопку этой команды.

  2. В свойстве команды Действие выберите процедуру УчебныйПример. Вставьте полный приведённый модуль формы.

  3. Откройте EPF в тонком или толстом клиенте Windows и нажмите кнопку. Не переносите Ждать и Асинх в серверный общий модуль.

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

  5. Эти методы проверяются по установленной справке 8.5.1.1343, но фактический запуск в 1С здесь не подтверждён.

&НаКлиенте
Перем ВыполняетсяУчебнаяЦепочка;

&НаКлиенте
Процедура УчебныйПример(Команда)
    Если ВыполняетсяУчебнаяЦепочка = Истина Тогда
        ВызватьИсключение "Дождитесь завершения собственной цепочки";
    КонецЕсли;
    Состояние = Новый Структура("Источник,Целевой,Буфер", Неопределено, Неопределено, Неопределено);
    Попытка
        Состояние.Источник = Новый ПотокВПамяти;
        Состояние.Целевой = Новый ПотокВПамяти;
        ИсходныйБуфер = Новый БуферДвоичныхДанных(5);
        Для ИндексБайта = 0 По 4 Цикл
            ИсходныйБуфер.Установить(ИндексБайта, (ИндексБайта + 1) * 10);
        КонецЦикла;
        ВыполняетсяУчебнаяЦепочка = Истина;
        Состояние.Источник.НачатьЗапись(ОповещениеПотока("ПослеЗаписи", Состояние), ИсходныйБуфер, 1, 3);
    Исключение
        ВыполняетсяУчебнаяЦепочка = Ложь;
        ОшибкаЗапуска = ОписаниеОшибки();
        ОшибкиЗакрытия = ЗакрытьСобственныеПотоки(Состояние.Источник, Состояние.Целевой);
        ВызватьИсключение ОшибкаЗапуска + " " + ОшибкиЗакрытия;
    КонецПопытки;
КонецПроцедуры

&НаКлиенте
Функция ОповещениеПотока(ИмяОбработчика, Состояние)
    Возврат Новый ОписаниеОповещения(ИмяОбработчика, ЭтаФорма, Состояние, "ОшибкаУчебнойЦепочки", ЭтаФорма);
КонецФункции

&НаКлиенте
Процедура ОшибкаУчебнойЦепочки(Ошибка, СтандартнаяОбработка, Состояние) Экспорт
    ВыполняетсяУчебнаяЦепочка = Ложь;
    ОшибкиЗакрытия = ЗакрытьСобственныеПотоки(Состояние.Источник, Состояние.Целевой);
    Если Не ПустаяСтрока(ОшибкиЗакрытия) Тогда
        Сообщить(ОшибкиЗакрытия);
    КонецЕсли;
    СтандартнаяОбработка = Истина;
КонецПроцедуры

&НаКлиенте
Процедура ПослеЗаписи(Состояние) Экспорт
    Состояние.Источник.НачатьПереход(ОповещениеПотока("ПослеПереходаИсточника", Состояние), 0, ПозицияВПотоке.Начало);
КонецПроцедуры

&НаКлиенте
Процедура ПослеПереходаИсточника(Позиция, Состояние) Экспорт
    Сообщить(Позиция = 0);
    Состояние.Источник.НачатьКопированиеВ(ОповещениеПотока("ПослеКопирования", Состояние), Состояние.Целевой, 2);
КонецПроцедуры

&НаКлиенте
Процедура ПослеКопирования(Скопировано, Состояние) Экспорт
    Сообщить(Скопировано = 2);
    Состояние.Целевой.НачатьПолучениеРазмера(ОповещениеПотока("ПослеРазмера", Состояние));
КонецПроцедуры

&НаКлиенте
Процедура ПослеРазмера(Размер, Состояние) Экспорт
    Сообщить(Размер = 2);
    Состояние.Целевой.НачатьУстановкуРазмера(ОповещениеПотока("ПослеУсечения", Состояние), 1);
КонецПроцедуры

&НаКлиенте
Процедура ПослеУсечения(Состояние) Экспорт
    Состояние.Целевой.НачатьСбросБуферов(ОповещениеПотока("ПослеСброса", Состояние));
КонецПроцедуры

&НаКлиенте
Процедура ПослеСброса(Состояние) Экспорт
    Состояние.Целевой.НачатьПереход(ОповещениеПотока("ПослеПереходаПриемника", Состояние), 0, ПозицияВПотоке.Начало);
КонецПроцедуры

&НаКлиенте
Процедура ПослеПереходаПриемника(Позиция, Состояние) Экспорт
    Сообщить(Позиция = 0);
    Состояние.Буфер = Новый БуферДвоичныхДанных(5);
    Для ИндексБайта = 0 По 4 Цикл
        Состояние.Буфер.Установить(ИндексБайта, 9);
    КонецЦикла;
    Состояние.Целевой.НачатьЧтение(ОповещениеПотока("ПослеЧтения", Состояние), Состояние.Буфер, 2, 3);
КонецПроцедуры

&НаКлиенте
Процедура ПослеЧтения(Прочитано, Состояние) Экспорт
    Сообщить(Прочитано = 1);
    Сообщить(Состояние.Буфер.Получить(2) = 20);
    Сообщить(Состояние.Буфер.Получить(3) = 9);
    Состояние.Целевой.НачатьЗакрытие(ОповещениеПотока("ПослеЗакрытияПриемника", Состояние));
КонецПроцедуры

&НаКлиенте
Процедура ПослеЗакрытияПриемника(Состояние) Экспорт
    Состояние.Целевой = Неопределено;
    Состояние.Источник.НачатьЗакрытие(ОповещениеПотока("ПослеЗакрытияИсточника", Состояние));
КонецПроцедуры

&НаКлиенте
Процедура ПослеЗакрытияИсточника(Состояние) Экспорт
    Состояние.Источник = Неопределено;
    ВыполняетсяУчебнаяЦепочка = Ложь;
    Сообщить("Собственная цепочка завершена, оба потока закрыты");
КонецПроцедуры

&НаКлиенте
Функция ЗакрытьСобственныеПотоки(Первый, Второй)
    Ошибки = "";
    Если Первый <> Неопределено Тогда
        Попытка
            Первый.Закрыть();
        Исключение
            Ошибки = "Первый поток не закрыт: " + ОписаниеОшибки();
        КонецПопытки;
    КонецЕсли;
    Если Второй <> Неопределено Тогда
        Попытка
            Второй.Закрыть();
        Исключение
            Ошибки = Ошибки + " Второй поток не закрыт: " + ОписаниеОшибки();
        КонецПопытки;
    КонецЕсли;
    Возврат Ошибки;
КонецФункции

Разбор по шагам

  1. Каждый следующий этап начинается только из экспортного обработчика предыдущего, не сразу после НачатьЗапись.

  2. После записи, установки размера, сброса буферов и закрытия обработчик получает только Состояние. После перехода — Позиция и Состояние, после копирования/чтения — фактическое количество и Состояние.

  3. Источник содержит 20/30/40; приёмник после копирования 20/30, после сокращения 20. В чтении возвращается 1, а не запрошенные 3.

  4. Все ОписаниеОповещения сохраняют ту же структуру ресурсов и назначают экспортный обработчик ошибки с тремя параметрами: Ошибка, СтандартнаяОбработка, Состояние.

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

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

Как проверить результат

  1. Семь контрольных сравнений дают Истина, в конце сообщение о завершении собственной цепочки.

  2. Повторный запуск во время выполнения запрещён; после завершения разрешён. Ошибки API не превращаются в успешное завершение.

Ожидаемый результат

Показаны все этапы настоящего конвейера оповещений и жизненный цикл собственных ресурсов.

На что обратить внимание

  1. Экспорт и сигнатуры обработчиков обязательны; не добавляйте лишний аргумент Количество после записи или закрытия.

  2. Структура передаётся как дополнительный параметр оповещения, не как объект результата чтения.

  3. Не заменяйте ошибки освобождения пустым Исключение; не запускайте следующий этап до оповещения.

Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.