8.х Многопоточный код

Тема в разделе "Отчеты и обработки для "1С:Предприятие 8"", создана пользователем Ivan2014, 5 ноя 2015.

  1. TopicStarter Overlay
    Ivan2014
    Offline

    Ivan2014 Опытный в 1С

    Регистрация:
    10 апр 2014
    Сообщения:
    384
    Симпатии:
    2
    Баллы:
    29
    Здравствуйте. Не могу разобраться с многопоточным кодом.
    Внес изменения в код:
    Код:
    //ранее формируется моя ТЗ, в ней около 1000 значений
    // определяем максимальное количество потоков
        ЧислоПотоков = 1;
        ЧислоСтрокВТаблице = ТЗ.Количество();
        // объем порции данных для обработки каждым потоком
        РазмерПорции = Цел(ЧислоСтрокВТаблице/ЧислоПотоков);
        // массив, где будут храниться фоновые задания
        МассивЗаданий = Новый Массив;
        Для НомерПотока = 1 По ЧислоПотоков Цикл
            // определяем индекс для начала обработки данных данным потоком
            // разные потоки обрабатывают разные части таблицы
            ИндексНачала = (НомерПотока - 1)*РазмерПорции;
            Если (НомерПотока = ЧислоПотоков) Тогда
                // если это последний поток, то он обрабатывает все оставшиеся данные
                // т.к. число потоков может не быть кратно количеству строк в таблице
                РазмерПорции = ЧислоСтрокВТаблице -(ЧислоПотоков*РазмерПорции)+РазмерПорции;
            КонецЕсли;
            // определяем массив параметров для процедуры
            НаборПараметров = Новый Массив;
            НаборПараметров.Добавить(ТЗ);
            НаборПараметров.Добавить(ИндексНачала);
            НаборПараметров.Добавить(РазмерПорции);
            // запуск фонового задания
            Задание = ФоновыеЗадания.Выполнить("ФоновоеЗаданиеМногопоточность", НаборПараметров);
            // добавляем задание в массив, чтобы потом отследить выполнение
            МассивЗаданий.Добавить(Задание);
        КонецЦикла;
        // проверим результат выполнения фоновых заданий
        Если МассивЗаданий.Количество() > 0 Тогда
            Попытка
                ФоновыеЗадания.ОжидатьЗавершения(МассивЗаданий);
            Исключение
                // действия в случае ошибки
            КонецПопытки;
        КонецЕсли;
    Для примера простейшая функция, она расположена в модуле объекта внешней обработки:
    Код:
    Процедура ФоновоеЗаданиеМногопоточность (ТЗ,ИндексНачала,РазмерПорции) Экспорт
    Сообщить("Все работает!");
    КонецПроцедуры
    
    Но при запуске выдает ошибку:
    Недопустимое значение параметра (параметр номер '1') (ФоновоеЗаданиеМногопоточность)

    Что не так? Как передать параметр (процедуру)?
  2. Draco
    Offline

    Draco Модераторы Команда форума Модератор

    Регистрация:
    28 окт 2009
    Сообщения:
    13.628
    Симпатии:
    946
    Баллы:
    204
    1. Много потоков не нужно - максимум 8-10 потоков и то если сервернормальный и железо
    2.процедура где располагается? в описании в СП читал что написано?
    Имя экспортируемой процедуры или функции неглобального общего модуля, который может быть выполнен на сервере, в форме ИмяМодуля.ИмяМетода
    А у тебя где?
    Ivan2014 нравится это.
  3. nbIpKuH_BaH9I
    Offline

    nbIpKuH_BaH9I Модераторы Команда форума Модератор

    Регистрация:
    16 сен 2009
    Сообщения:
    6.978
    Симпатии:
    397
    Баллы:
    104
    Вот здесь прекрасная статья. http://infostart.ru/public/182139/. Пусть висит ссылка. Статья реально полезная. Сам по ней реализовал один раз такой механизм.
    Ivan2014 нравится это.
  4. TopicStarter Overlay
    Ivan2014
    Offline

    Ivan2014 Опытный в 1С

    Регистрация:
    10 апр 2014
    Сообщения:
    384
    Симпатии:
    2
    Баллы:
    29
    1. Я хочу в 4 потока запустить.
    2. Это внешняя обработка, расположено в модуле объекта. Я пробовал писать и общий объект. и другие варианты, не видит оно эту процедуру.
  5. Draco
    Offline

    Draco Модераторы Команда форума Модератор

    Регистрация:
    28 окт 2009
    Сообщения:
    13.628
    Симпатии:
    946
    Баллы:
    204
  6. TopicStarter Overlay
    Ivan2014
    Offline

    Ivan2014 Опытный в 1С

    Регистрация:
    10 апр 2014
    Сообщения:
    384
    Симпатии:
    2
    Баллы:
    29
    По крайней статье я и делал. но я не могу понять что писать в:
    Код:
    ФоновыеЗадания.Выполнить("ВыгрузкаДанныхНаСервере.ВыгрузитьДанныеПоПартиям", МассивПараметров);
    У меня это внешняя обработка, экспортная процедура расположена в модуле объекта и называется ФоновоеЗаданиеМногопоточность.
    --- Объединение сообщений, 5 ноя 2015 ---
    В скобочках что писать.
    --- Объединение сообщений, 5 ноя 2015 ---
    Так не работает:
    Код:
    Задание = ФоновыеЗадания.Выполнить("ФоновоеЗаданиеМногопоточность", НаборПараметров);
    
    --- Объединение сообщений, 5 ноя 2015 ---
    Метод задания не найден: МодульОбъекта:ФоновоеЗаданиеМногопоточность
  7. TopicStarter Overlay
    Ivan2014
    Offline

    Ivan2014 Опытный в 1С

    Регистрация:
    10 апр 2014
    Сообщения:
    384
    Симпатии:
    2
    Баллы:
    29
    Пришлось в общий модуль конфигурации процедуру переписать. Для общего модуля обработки не разобрался как код переписать.
  8. antares
    Offline

    antares Опытный в 1С

    Регистрация:
    30 ноя 2006
    Сообщения:
    340
    Симпатии:
    7
    Баллы:
    29
    ты к внешней обработке как обращаешься? наверно объект создаешь и через него уже процедуры и функции юзаешь, так вот укажи в первом параметре имя_объекта.Имя_процедуры_модуля
    Ivan2014 нравится это.
  9. TopicStarter Overlay
    Ivan2014
    Offline

    Ivan2014 Опытный в 1С

    Регистрация:
    10 апр 2014
    Сообщения:
    384
    Симпатии:
    2
    Баллы:
    29
    А какое будет имя объекта если эта процедура в модуле объекта моей обработки? В этом и вопрос. Я по всякому пробовал не получается. Решило только переписывание в общий модуль конфигурации, но это тестовая версия, в основной не хотелось бы так делать.
  10. Draco
    Offline

    Draco Модераторы Команда форума Модератор

    Регистрация:
    28 окт 2009
    Сообщения:
    13.628
    Симпатии:
    946
    Баллы:
    204
    Да процедура в общем модуле должна быть
    Ivan2014 нравится это.
  11. antares
    Offline

    antares Опытный в 1С

    Регистрация:
    30 ноя 2006
    Сообщения:
    340
    Симпатии:
    7
    Баллы:
    29
    2 Ivan2014
    Код:
    Процедура ИспользованиеВнешнейОбработки() Экспорт
        ВнешОбр = ВнешниеОбработки.Создать("ПримерВнешнейОбработки.epf");
        ВнешОбр.ЗапускМногопоточности();
    КонецПроцедуры
    вот такое имя и должно быть, имя созданного обяъекта, которым ты инициализируешь внешнюю обработку, ".", и имя процедуры в модуле внешней обработки; сервер работает с объектными именами, которые связаны с реальными объектами в данном сеансе; ты создал объект, связал с ним внешнюю обработку, и сервер работает с процедурами этой обработки через имя созданного объекта

    ты определяешь в модуле обработки только функционал обработки данных, т.е. части большой ТЗ; включает этот функционал общий модуль, в котором инициализируется новое фоновое задание; кстати, это не критично, если приложение обычное или управляемое, но сеанс под толстым клиентом
    Последнее редактирование: 6 ноя 2015
    Ivan2014 нравится это.
  12. TopicStarter Overlay
    Ivan2014
    Offline

    Ivan2014 Опытный в 1С

    Регистрация:
    10 апр 2014
    Сообщения:
    384
    Симпатии:
    2
    Баллы:
    29
    Большое спасибо за помощь, но что-то этот вариант у меня вообще не заработал.
    --- Объединение сообщений, 6 ноя 2015 ---
    В результате остановился на этом.
    Но почему то мой код не переходит в общий модуль.
    Код:
    ЧислоПотоков = 2;
        ЧислоСтрокВТаблице = ТЗ.Количество();
        // объем порции данных для обработки каждым потоком
        РазмерПорции = Цел(ЧислоСтрокВТаблице/ЧислоПотоков);
        // массив, где будут храниться фоновые задания
        МассивЗаданий = Новый Массив;
        Для НомерПотока = 1 По ЧислоПотоков Цикл
            // определяем индекс для начала обработки данных данным потоком
            // разные потоки обрабатывают разные части таблицы
            ИндексНачала = (НомерПотока - 1)*РазмерПорции;
            Если (НомерПотока = ЧислоПотоков) Тогда
                // если это последний поток, то он обрабатывает все оставшиеся данные
                // т.к. число потоков может не быть кратно количеству строк в таблице
                РазмерПорции = ЧислоСтрокВТаблице -(ЧислоПотоков*РазмерПорции)+РазмерПорции;
            КонецЕсли;
            // определяем массив параметров для процедуры
            НаборПараметров = Новый Массив;
            НаборПараметров.Добавить(ТЗ);
            НаборПараметров.Добавить(ИндексНачала);
            НаборПараметров.Добавить(РазмерПорции);
            // запуск фонового задания
            Задание = ФоновыеЗадания.Выполнить("ФоновоеЗаданиеМногопоточность.ФоновоеЗаданиеМногопоточность", НаборПараметров);
            //Задание = ФоновыеЗадания.Выполнить("ФоновоеЗаданиеМногопоточность", НаборПараметров);
            // добавляем задание в массив, чтобы потом отследить выполнение
            МассивЗаданий.Добавить(Задание);
        КонецЦикла;
        // проверим результат выполнения фоновых заданий
        Если МассивЗаданий.Количество() > 0 Тогда
            Попытка
                ФоновыеЗадания.ОжидатьЗавершения(МассивЗаданий);
            Исключение
                // действия в случае ошибки
            КонецПопытки;
        КонецЕсли;
    ставлю там точку останова не попадаю в него.
    Хотя в массив заданий 2 задания добавляется
    upload_2015-11-6_14-59-56.png
    далее код переходит в ожидадания завершения. и далее уже в общий мой код. не могу понять почему всего 2 значения попадают в МассивЗаданий и почему в общий модуль точка останова не переходит.
  13. Draco
    Offline

    Draco Модераторы Команда форума Модератор

    Регистрация:
    28 окт 2009
    Сообщения:
    13.628
    Симпатии:
    946
    Баллы:
    204
    База файловая или клиент серверная?
    Ivan2014 нравится это.
  14. antares
    Offline

    antares Опытный в 1С

    Регистрация:
    30 ноя 2006
    Сообщения:
    340
    Симпатии:
    7
    Баллы:
    29
    для отладки открой сеанс под толстым клиентом

    и если работаешь с файловой базой, то предварительно запусти сеанс, где периодически выполняй глобальную функцию ВыполнитьОбработкуЗаданий(); на один сеанс все не вешай, загнется; создай обработку с одной кнопкой ОбработатьЗадания и модуль формы поставь этот код
    Код:
    &НаКлиенте
    Процедура ВключитьОбработкуЗаданий(Команда)
        ВыполнитьЗадания();
    КонецПроцедуры
    
    &НаКлиенте
    Процедура ВыполнитьЗадания() Экспорт
        ВыполнитьОбработкуЗаданий();
        ПодключитьОбработчикОжидания("ВыполнитьЗадания", 10, Истина);
    КонецПроцедуры
    все, запустишь один сеанс под регламентным пользователем (см. роли), под ним запустишь эту обработку и активируешь менеджера; если платформа 8.3.5 и позднее, то делать это не надо, там просто сеанс запусти, а в другом работай с потоками

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

    кстати, интересно какими критериями руководствуется менеджер ФЗ при создании рабочих процессов в файловом варианте? количество процессоров, размер незадействованной памяти,...? как то скупо о природе этого пишут
    Последнее редактирование: 6 ноя 2015
    Ivan2014 нравится это.
  15. TopicStarter Overlay
    Ivan2014
    Offline

    Ivan2014 Опытный в 1С

    Регистрация:
    10 апр 2014
    Сообщения:
    384
    Симпатии:
    2
    Баллы:
    29
    База клиент-серверная.
    --- Объединение сообщений, 6 ноя 2015 ---
    Но я код не делил
    &НаКлиенте
    и
    &Насервере
    у меня общий код 8.2 обычное приложение.
  16. antares
    Offline

    antares Опытный в 1С

    Регистрация:
    30 ноя 2006
    Сообщения:
    340
    Симпатии:
    7
    Баллы:
    29
    если база клиент-серверная, и приложение обычное, то все еще проще, на сервере инициализацией менеджера ФЗ занимается планировщик заданий из менеджера кластера; в общем модуле, в процедуре запуска фоновых заданий поставь точку останова и посмотри в отладке сколько циклов отрабатывает, возможно остальные выполняются очень быстро и завершаются, потоки выполняются независимо; поставь исключение на метод Выполнить с выводом тестовых данных в сообщениях
    Последнее редактирование: 6 ноя 2015
    Ivan2014 нравится это.
  17. TopicStarter Overlay
    Ivan2014
    Offline

    Ivan2014 Опытный в 1С

    Регистрация:
    10 апр 2014
    Сообщения:
    384
    Симпатии:
    2
    Баллы:
    29
    Отрабатывается столько циклов - сколько потоков я использую. А до моей процедуры в общем модуле (точка останова на ней) почему то код не выполняется, не переходит на эту точку останова.
  18. TopicStarter Overlay
    Ivan2014
    Offline

    Ivan2014 Опытный в 1С

    Регистрация:
    10 апр 2014
    Сообщения:
    384
    Симпатии:
    2
    Баллы:
    29
    Вот мой код в обработке:
    Код:
    ТЗ=Запрос.Выполнить().Выгрузить();//в ТЗ загружается примерно 1000 строк
       
        Колво=ТЗ.Количество();
        СчДляОтчета=0;
       
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // определяем максимальное количество потоков
        ЧислоПотоков = 4;
        ЧислоСтрокВТаблице = ТЗ.Количество();
        // объем порции данных для обработки каждым потоком
        РазмерПорции = Цел(ЧислоСтрокВТаблице/ЧислоПотоков);
        // массив, где будут храниться фоновые задания
        МассивЗаданий = Новый Массив;
        Для НомерПотока = 1 По ЧислоПотоков Цикл
            // определяем индекс для начала обработки данных данным потоком
            // разные потоки обрабатывают разные части таблицы
            ИндексНачала = (НомерПотока - 1)*РазмерПорции;
            Если (НомерПотока = ЧислоПотоков) Тогда
                // если это последний поток, то он обрабатывает все оставшиеся данные
                // т.к. число потоков может не быть кратно количеству строк в таблице
                РазмерПорции = ЧислоСтрокВТаблице -(ЧислоПотоков*РазмерПорции)+РазмерПорции;
            КонецЕсли;
            // определяем массив параметров для процедуры
            НаборПараметров = Новый Массив;
            НаборПараметров.Добавить(ТЗ);
            НаборПараметров.Добавить(ИндексНачала);
            НаборПараметров.Добавить(РазмерПорции);
            // запуск фонового задания
            Задание = ФоновыеЗадания.Выполнить("ФоновоеЗаданиеМногопоточность.ФоновоеЗаданиеМногопоточность", НаборПараметров);
            //Задание = ФоновыеЗадания.Выполнить("ФоновоеЗаданиеМногопоточность", НаборПараметров);
            // добавляем задание в массив, чтобы потом отследить выполнение
            МассивЗаданий.Добавить(Задание);
        КонецЦикла;
        // проверим результат выполнения фоновых заданий
        Если МассивЗаданий.Количество() > 0 Тогда
            Попытка
                ФоновыеЗадания.ОжидатьЗавершения(МассивЗаданий);
            Исключение
                // действия в случае ошибки
            КонецПопытки;
        КонецЕсли;
    А вот сама процедура во внешнем модуле:
    Код:
    Процедура ФоновоеЗаданиеМногопоточность (ТЗ,ИндексНачала,РазмерПорции) Экспорт
    Сообщить("Работает!");
    КонецПроцедуры
    
    В МассивЗаданий передается количество заданий = числу потоков
    upload_2015-11-7_19-21-2.png


    далее код переходит в ФоновыеЗадания.ОжидатьЗавершения(МассивЗаданий);
    но стоит точка останова в ФоновоеЗаданиеМногопоточность, вот туда не переходит код.
    Возможно я что-то с галочками напутал:?
    upload_2015-11-7_19-24-19.png
  19. nbIpKuH_BaH9I
    Offline

    nbIpKuH_BaH9I Модераторы Команда форума Модератор

    Регистрация:
    16 сен 2009
    Сообщения:
    6.978
    Симпатии:
    397
    Баллы:
    104
    Конечно не переходит, он же на сервере выполняется. Хотите отладить код выполняющийся на сервере, то необходимо запустить сервер в режиме отладки.
    1. Остановить службу 1C:Enterprise 8.2 Server Agent
    2. Запустить редактор системного реестра. Что бы открыть редактор реестра необходимо нажать Windows + R (или Пуск-Выполнить) ввести в командную строку regedit.
    3. Найти ветку реестра [HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\services\1C:Enterprise 8.2 Server Agent\]
    4. Находим свойство «ImagePath»= , добавляем в строку «-debug».
    5. Записываем и запускаем службу.
    Пример:
    До включения:
    «»C:\Program Files (x86)\1cv82\8.2.18.109\bin\ragent.exe» -srvc -agent -regport 1541 -port 1540 -range 1560:1591 -d «C:\Program Files (x86)\1cv82\srvinfo»»
    После включения отладки:
    «»C:\Program Files (x86)\1cv82\8.2.18.109\bin\ragent.exe» -srvc -agent -regport 1541 -port 1540 -range 1560:1591 -d «C:\Program Files (x86)\1cv82\srvinfo» -debug»
    Затем в конфигураторе в предметах отладки необходимо сделать следующее.
    upload_2015-11-8_9-27-30.png
    Установить точку останова. И в этом случае управление перейдет в отладкик. Только есть один маленький нюанс. Имя информационной базы и сервера должно точно соответствовать имени ИБ и сервера, воспринимаемого сервером. Верхний и нижний регистр очень важны. Поэтому можно узнать это наверняка
    Код:
    ЗаписьЖурналаРегистрации("ОТЛАДКА",,,, СтрокаСоединенияИнформационнойБазы())
    Пропишите точно также у себя в списке баз и будет счастье.
    Ivan2014 и antares нравится это.
  20. TODD22
    Offline

    TODD22 Профессионал в 1С Команда форума

    Регистрация:
    23 фев 2009
    Сообщения:
    4.755
    Симпатии:
    146
    Баллы:
    104
    То же заинтересовался многопоточной загрузкой. Есть у меня порядка 150 файлов.
    Мне их нужно грузить каждый день да ещё и по несколько раз. В них содержаться цены номенклатуры.
    Допустим сделаю 3 потока(процессор на сервере 8 ядерный).

    Но тут есть один нюанс. У меня всё записывается в регистр сведений "цены". Он независимый. А блокировки в базе табличные.

    Не будет ли проблем при записи в сам регистр? Если я в 3х потоках начну грузить не будут ли они конфликтовать на записи в регистр?

Поделиться этой страницей