Опровержение многопоточного выполнения простым способом

02.11.26

Разработка - Инструментарий разработчика

Ранее публиковал описание метода простой многопоточности. В ходе тесной эксплуатации выяснился важный баг платформы, который временами делает невозможным получение результатов из фоновых заданий. Происходит такое только в толстом клиенте. У предыдущей статьи почти 8 тысяч просмотров, лайков больше 20. Меня это обязывает. Расскажу, как обойти эту проблему, если все равно не хочется прибегать к сложным конвейерам, а многопоточность нужна, заодно привнесу пару новинок.

Бесплатные

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Узнавайте о новых бесплатных решениях в нашей телеграм-группе Инфостарт БЕСПЛАТНО

Наименование Скачано Бесплатно
Проверка бага 8.3.27+ Совместимость не важна
.cf 143,91Kb
5 Скачать бесплатно
Модуль многопоточного выполнения (bsl)
.bsl 65,39Kb
5 Скачать бесплатно
Проверка бага меньшие версии (немного другой алгоритм)
.cf 73,34Kb
4 Скачать бесплатно

Вы можете заказать платную доработку или адаптацию этой разработки под вашу конфигурацию на «Бирже заказов».

  • 0% комиссии — оплата напрямую исполнителю;
  • Исполнители любого масштаба — от отдельных специалистов до команд под проект;
  • Прямой обмен контактами между заказчиком и исполнителем;
  • Безопасная сделка — при необходимости;
  • Рейтинги, кейсы и прозрачная система откликов.

1. Вступление

2. Обновленное решение

3. Подробнее про ошибку

4. Заключение

 

1. Вступление

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

Ах, вы еще здесь. Ну тогда рассказываю: в текущей версии 1С на нашем предприятии (8.3.27.2325), да и ранее, как выясняется, иногда невозможно получить из временного хранилища данные, положенные туда в подчиненном фоновом задании. А ведь это основной способ обмена информацией при многопоточном выполнении без задействования сторонних регистров. Происходит это обычно после обеда, причем иногда такая возможность возвращается сама собой, иногда требуется перезапуск сеанса. Происходит такое хаотично, но достаточно часто: задействовал этот механизм на отдел 10-15 человек, так ежедневно у 2-3 такое происходило. Там нет многопоточного выполнения, просто фоновое задание, которое выполняет работу, в ходе которой 1С спонтанно подвисала. После обнаружения и почти бесплодных попыток обойти ошибку без перезапуска сеанса перешел на уведомления клиента и доволен уже несколько месяцев. А вот когда пришел черед многопоточности тут я и вспомнил свои приключения, которые почему-то по наивности своей не связал в простую казалось бы цепочку, уж извините, кому моя предыдущая статья пригодилась! Дело в том, что до недавнего времени возвращение результатов при многопоточном выполнении я задействовал только эпизодически, в основную работали методы, которые этого не требуют, поэтому и был уверен, что все стабильно. А вот нет! Самое худшее, что при получении данных стоит стандартная проверка на Неопределено, которая срабатывает втихую, ни о чем не оповещая, мало ли какой должен быть результат у функции! Ну да будет корить себя, расскажу как просто обойти данный баг платформы, если вам довелось работать в толстом клиенте, не задействуя сбойный механизм, но и не углубляясь в допиливание конфигурации. Но перед этим отмечу, что вот уведомления клиента радуют - эта ловушка ни разу за несколько месяцев не сработала, а ведь используется очень активно:

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

 

2. Обновленный алгоритм с задействованием регистра

Итак, без регистров в многопоточности в некоторых случаях не обойтись, если нужны результаты, добавляем простой регистр сведений (непериодический) - РезультатыВыполненияФункций:

1. Измерение - КлючЗадания - Строка(36) - Идентификатор задания на многопоточную обработку, используется как наименование для всех его потоков, а соответственно, и их результатов

2. Измерение - НомерПорции - Число(15) - Номер порции в задании на обработку

3. Ресурс - Результаты - ХранилищеЗначения - сюда будут помещаться результаты обработки порций в сериализованном виде

Далее, для запуска порции используем не метод ВыполнитьБезопасно, который внезапно переделывается в функцию, а другой:

// Выполняет указанную функцию и сохраняет полученный результат в регистр сведений.
//
// Параметры:
//   ВыполняемыйМетод - Строка - имя выполняемого метода.
//   Параметры - Массив Из Произвольный - параметры выполняемого метода.
//   НастройкиВыполнения - Структура - см. НастройкиВыполнения().
//   НомерПорции - Число - номер порции результатов выполнения.
Процедура ВыполнитьФункцию(ВыполняемыйМетод, Параметры, НастройкиВыполнения, НомерПорции) Экспорт

    Результат = ВыполнитьБезопасно(ВыполняемыйМетод, Параметры, , НастройкиВыполнения.ВозвращатьРезультаты);
    Если Результат = Неопределено Тогда
        Если НастройкиВыполнения.ВозвращатьРезультаты Тогда
            ЗаписьЖурналаРегистрации(НастройкиВыполнения.ПотокЖурналаРегистрации, УровеньЖурналаРегистрации.Предупреждение,
                , ВыполняемыйМетод, "Обработка порции должна вернуть значение, а получено Неопределено. "
                + "Номер порции - " + НомерПорции);
        КонецЕсли;
    Иначе
        МенеджерЗаписи = РегистрыСведений.РезультатыВыполненияФункций.СоздатьМенеджерЗаписи();
        МенеджерЗаписи.КлючЗадания = НастройкиВыполнения.КлючЗадания;
        МенеджерЗаписи.НомерПорции = НомерПорции;
        МенеджерЗаписи.Результаты = Новый ХранилищеЗначения(Результат);
        МенеджерЗаписи.Записать();
    КонецЕсли;
        
КонецПроцедуры

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

1. ВыполнятьФоном - Истина, когда хочется освободить форму и получать прогресс не только в обычном приложении, но и в управляемых формах

2. ЭтоФоновоеВыполнение - Вспомогательное поле, его не трогать

3. КлючЗадания - строка уникального идентификатора для идентификации заданий и отправки/получения уведомления о прогрессе и окончании.

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

НастройкиВыполнения = МногопоточноеВыполнение.НастройкиВыполнения(ЧислоПотоков, 1000, , Ложь);
МногопоточноеВыполнение.ВыполнитьФункциюПорциями(НаборСлов, 
	"Обработки.ДемонстрацияМногопоточнойРаботы.НагрузитьСправочникТоварыПоПорциям",
	Новый Массив, НастройкиВыполнения);

Здесь НаборСлов - это простой массив, который надо обработать порциями, соответственно метод идет вторым параметром. Третьим параметром идет массив последующих параметров, которые должны быть переданы в каждую порцию (здесь их нет). Ну и четвертым - НастройкиВыполнения, полученные из функции. Одноименная функция принимает на вход четыре параметра: число потоков, размер порции (необязательно), останавливать при авариях (по умолчанию Ложь) и возвращать результаты (по умолчанию Истина, да-да). Также настройки могут быть изменены вручную, описание в предыдущей статье, повторяться не буду.

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

&НаКлиенте ...
НастройкиВыполнения = МногопоточноеВыполнение.НастройкиВыполнения(ЧислоПотоков, 100);
НастройкиВыполнения.ВыполнятьФоном = Истина;
УведомленияКлиента.ПодключитьОбработчик(НастройкиВыполнения.КлючЗадания,
    Новый ОписаниеОповещения("ПодчиститьСправочникТоварыУведомление", ЭтотОбъект));
&НаСервере ...
МногопоточноеВыполнение.ВыполнитьФункциюПорциями(РезультатЗапроса
    , "Обработки.ДемонстрацияМногопоточнойРаботы.ПодчиститьСправочникТоварыПоПорциям", 
    Новый Массив, НастройкиВыполнения);	
&НаКлиенте ...
Состояние(Результат.ТекстСообщения, Результат.Прогресс);
Для Каждого Сообщение Из Результат.Сообщения Цикл
    ОбщегоНазначенияКлиент.СообщитьПользователю(Сообщение);
КонецЦикла;
...
МногопоточноеВыполнение.ПополнитьРезультаты(НеудаляемаяНоменклатура, Результат.НастройкиВыполнения,
    Результат.КоличествоПорций);
УведомленияКлиента.ОтключитьОбработчик(Результат.НастройкиВыполнения.КлючЗадания);

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

 
 Тот же сценарий полностью, с комментариями

Если кто-то все же пользуется описанным в предыдущей статье подходом, то обратите внимание, что функция обработки порции теперь это функция, которая возвращает значение, а соответственно, второй параметр АдресРезультата теперь не нужен - стало проще использовать обычную функцию и для фоновой работы, и для сеансовой.

 

3. Подробнее об ошибке платформы

В чем вообще суть? Для тех, кто не в курсе, в 1С есть только один способ получения данных временного хранилища из другого сеанса и работает он для подчиненных фоновых заданий. Вы помещаете во временное хранилище пустое значение (Неопределено) и полученный адрес передаете в запускаемое фоновое задание в качестве параметра. Когда задание обработало данные, оно может (один раз) поместить результат по этому адресу. Тогда, по его завершении, вызывающий его сеанс может обычным способом через ПолучитьИзВременногоХранилища подтянуть этот результат и обработать его. До Уведомлений клиента это был практически единственный без использования регистров штатный механизм обмена данными с фоновым заданием. И тут такая засада. Хорошо, что только в толстом клиенте при получении именно на клиенте. Причем, что характерно, если разорвать клиентский вызов после завершения задания (например, обработчиком ожидания) и обратиться по адресу снова, то скорее всего результат будет уже там, но если пытаться сделать это в цикле, то можно запросто прождать пару минут даже на простых примерах.

Проверил баг на трех-четырех серверах - везде он проявляется. Версии 8.5.1.1529 и 8.3.25.1633 также этой ошибке подвержены. Удалось зафиксировать его и на тестовой мини-базе, ее к статье прилагаю, можете проверить свой сервер. Напомню, что баг проявляется только в толстом клиенте, поэтому проверять надо именно в нем, если вы его, конечно, используете. Оставлял в тонком клиенте на сутки, проблем пока не обнаружено. В файловой базе также зафиксировать ошибки не удалось. Если получать в толстом клиенте, но на сервере, ошибка также не проявляется (запускал на несколько часов). То есть если говорить о многопоточной обработке, то фактически можно просто перенести метод ВыполнитьФункциюПорциями с основной обвязкой в серверный модуль и все будет хорошо, а заодно и количество неявных обращений к серверу сократите, но тогда не будет отображения состояния. Да и в общем случае в том же обычном приложении не всегда удобно переносить контекст на сервер, для этого может понадобиться городить велосипед.

Разумеется, тестовая база не повторяет ошибку в полной мере, потому что стабильного неполучения результата, как в рабочей, мне добиться не удалось. А ведь последний раз такое случилось после 3 часов дня сразу у двух пользователей, которые только и использовали данный механизм. Запуск теста на длительное время дает достаточно много ошибок, которые иногда повторяются совсем рядом, но не более того. Возможно, есть еще какой-то фактор. Пробовал настраивать перезапуск серверного процесса каждые 5 минут - ошибок как будто больше, но не более того. Пробовал запускать тест надолго - за ночь не набралось и 50 ошибок, причем собственно ночью не было ни одной, скорее всего все-таки план питания сработал, но 6 часов тест точно работал, а ведь в нем частота обращений гораздо выше. Пробовал повышать нагрузку, снижать ее в ноль - ошибки стабильно есть, даже если все, что вы делаете в фоновом задании - это получаете случайное число! Что передаете тоже как будто неважно, по крайней мере для числа и таблицы значений с ссылочными типами разницы особой нет. Запускать надо хотя бы на час-два. Да, первая ошибка обычно вылезает в первые минуты, но так происходит не всегда.

По поводу получения при ошибке в основном со второй попытки. Да, если предпринять повторные попытки даже через несколько секунд, то есть вероятность таки получить результат. Но хочется отметить, что даже в тесте иногда получаются данные только с 3 попытки, а это около 5 секунд. А в рабочей базе настраивал повторные попытки раз в минуту-две. Так в журналах увидел и получение с 27 попытки, и 190 безуспешных попыток (что чаще) до тех пор, пока форму не закрыли. Но достаточно часто также данные получались со второй попытки.

 

4. Заключение

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

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

Если вам интересно попробовать многопоточную работу на тестовой базе, можете поискать на gitflic по ключевым словам "Фоновые задания". Это проект EDT, в нем есть обработка "Демонстрация многопоточной работы" с основными примерами, данные для заполнения в макетах. Также по поводу очистки записей с результатами. На моем тестовом сервере она занимает от нескольких мс до 0.4 с (для одних и тех же данных), что уже ощутимо. Если на вашем она занимает долго по времени - в проекте есть форма списка регистра, на ней есть команда очистки устаревших записей. Думаю, будет несложно перенести ее в любое подходящее регламентное задание.

Вступайте в нашу телеграмм-группу Инфостарт

Многопоточная обработка извините баг платформы фоновые задания ПолучитьИзВременногоХранилища Неопределено толстый клиент

См. также

Разработка Инструментарий разработчика Групповая разработка (Git, хранилище) Разработчик Платные (руб)

Практический курс по работе с AI-агентами для разработчиков 1С уровня middle и senior, а также тимлидов команд: от постановки задач и передачи контекста до создания расширений, интеграций, MCP-инструментов, тестов и проверки готового решения.

50000 руб.

10.09.2026    13329    115    0    

78

Инструментарий разработчика Чистка данных Свертка базы Инструменты администратора БД Системный администратор Разработчик Руководитель проекта 1С:Предприятие 8 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 Россия Платные (руб)

Инструмент представляет собой обработку для проведения свёртки или обрезки баз данных. Работает на ЛЮБЫХ конфигурациях (УТ, БП, ERP, УНФ, КА и т.д.). Поддерживаются серверные и файловые базы, управляемые и обычные формы, интерфейс 8.5. Может выполнять свертку одновременно в несколько потоков, а также без непосредственного участия пользователя. Решение в Реестре отечественного ПО.

24900 руб.

20.08.2024    83206    432    171    

361

Инструментарий разработчика Роли и права Запросы СКД Разработчик Руководитель проекта 1С:Предприятие 8 Платные (руб)

Инструменты для разработчиков 1С 8.3 и 8.5: Infostart Toolkit. Автоматизация и ускорение разработки на управляемых формах. Легкость работы с 1С.

16500 руб.

02.09.2020    285575    1606    423    

1220

Инструментарий разработчика Разработка Администрирование веб-серверов Системный администратор Разработчик Аналитик Руководитель проекта 1С 8.3 Платные (руб)

Analyzer 1C сводит выгрузку 1С — основную конфигурацию и все расширения — в единый граф знаний. Любой запрос по связям за доли секунды, с пометками «Доб.» / «Заимств.» / «Переопределено». Новое в 2.0 — обновление поставки: сравнение и объединение версий деревом «как в Конфигураторе» с выгрузкой плана решений; поиск конфликтов из-за перехватов расширений и висячих ссылок; загрузка из бинарных .cf/.cfe; циклические зависимости. Плюс анализ влияния, запросы BSL, роли и RLS, граф вызовов. Минута на развёртывание через Docker без необходимости подключения к Интернет. Любая 1С:Предприятие 8.3+.

14000 руб.

17.04.2026    16720    63    62    

73

Пакетная печать Печатные формы Инструментарий разработчика Разработчик 1С:Предприятие 8 Платные (руб)

Расширение для создания и редактирования печатных форм в системе 1С:Предприятие 8.3. Благодаря конструктору можно значительно снизить затраты времени на разработку печатных форм, повысить качество и прозрачность разработки, а также навести порядок в многообразии корпоративных печатных форм. Обновление версии от 21.04.26

22570 руб.

06.10.2023    44150    122    54    

135

Инструментарий разработчика Нейросети Платные (руб)

Первые попытки разработки на 1С с использованием больших языковых моделей (LLM) могут разочаровать. LLMки сильно галлюцинируют, потому что не знают устройства конфигураций 1С, не знают нюансов синтаксиса. Но если дать им подсказки с помощью MCP, то результат получается кардинально лучше. Далее в публикации: MCP для поиска по метаданным 1С, справке синтакс-помощника и проверки синтаксиса.

15250 руб.

25.08.2025    76805    147    41    

154

Разработка Инструментарий разработчика Разработчик Руководитель проекта 1С 8.3 Платные (руб)

Pilot 1C превращает задачу, поставленную обычными словами, в техническое задание, код на встроенном языке и сценарии проверки. Прежде чем что-то предложить, он сверяется с устройством вашей конфигурации через граф Analyzer 1C: существует ли объект, из чего он состоит, кто его вызывает, какие роли дают права. Чего найти не удалось – спрашивает, а не выдумывает. Готовый код проходит более полутора сотен проверок по справочнику языка и стандартам разработки, который приезжает вместе с продуктом. Модель – ваша: любой сервер, совместимый с программным интерфейсом OpenAI, в том числе локальный. Правки в конфигурацию Pilot не вносит – их применяет разработчик.

18300 руб.

11.09.2026    3694    5    0    

10

Инструменты администратора БД Инструментарий разработчика Роли и права Разработчик 1С:Предприятие 8 1C:Бухгалтерия Россия Платные (руб)

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

17000 руб.

10.11.2023    28712    103    46    

107
Для отправки сообщения требуется регистрация/авторизация