Добрый день!
Изучаю фоновые задания для дальнейшей возможности распараллеливания процессов. Есть простая задача - выгрузить один объект в другие базы через файл.
Реализация выгрузки:
Процедура ВыгрузитьОбъектВXML(Объект, ИмяФайла, МассивПапок) Экспорт
ПолноеИмяФайла = КаталогВременныхФайлов() + ИмяФайла;
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл(ПолноеИмяФайла);
ЗаписьXML.ЗаписатьОбъявлениеXML();
ЗаписатьXML(ЗаписьXML, Объект);
ЗаписьXML.Закрыть();
Для каждого ПапкаВыгрузки Из МассивПапок Цикл
МассивПараметров = Новый Массив;
МассивПараметров.Добавить(Выборка.ПапкаВыгрузки);
МассивПараметров.Добавить(ИмяФайла);
МассивПараметров.Добавить(ПолноеИмяФайла);
Задание = ФоновыеЗадания.Выполнить("МодульТест.СкопироватьФайлВКаталог", МассивПараметров);
МассивЗаданий.Добавить(Задание);
//СкопироватьФайлВКаталог(Выборка.ПапкаВыгрузки, ИмяФайла, ПолноеИмяФайла); // Вариант без фоновых заданий
КонецЦикла;
// чтобы удалить файл создадим фоновое задание которое дождется завершения всех заданий и после этого удалит файл
МассивПараметров = Новый Массив;
МассивПараметров.Добавить(МассивЗаданий);
МассивПараметров.Добавить(ПолноеИмяФайла);
Задание = ФоновыеЗадания.Выполнить("МодульТест.ДождатьсяВыполненияФоновыхЗаданийИУдалитьФайл", МассивПараметров);
Конецпроцедуры
Процедура СкопироватьФайлВКаталог(ПапкаВыгрузки, ИмяФайла, ПолноеИмяФайла) Экспорт
Попытка
ФайлНаДиске = Новый Файл(ПапкаВыгрузки + "\" + ИмяФайла);
Если ФайлНаДиске.Существует() Тогда
Возврат;
КонецЕсли;
КопироватьФайл(ПолноеИмяФайла, ПапкаВыгрузки + "\" + ИмяФайла);
Исключение
ТекстОшибки = "Ошибка при копировании файла " + ИмяФайла + " в папку: " + ПапкаВыгрузки + символы.ПС + ОписаниеОшибки();
СообщитьОбОшибке(ТекстОшибки, ПапкаВыгрузки);
КонецПопытки;
КонецПроцедуры
Процедура ДождатьсяВыполненияФоновыхЗаданийИУдалитьФайл(МассивЗаданий, ПолноеИмяФайла) Экспорт
Если МассивЗаданий.Количество() > 0 Тогда
Попытка
ФоновыеЗадания.ОжидатьЗавершения(МассивЗаданий);
УдалитьФайлы(ПолноеИмяФайла);
Исключение
КонецПопытки;
МассивЗаданий.Очистить();
КонецЕсли;
КонецПроцедуры
Показать
В результате при запуске фонового задания получаю сообщение:
Ошибка при вызове метода контекста (КопироватьФайл): Ошибка копирования файлов: Ошибка копирования файлов из 'c:\temp\Номенклатура_0034771000002395740.xml' в 'd:\temp\Номенклатура_0034771000002395740.xml' : Файл не обнаружен
Работаю в клиент-серверном варианте. Вызов производится при записи объекта.
права на папку для пользователя, под которым стартует сервер 1с даны (он так же локально работает).
В папке C:\Temp файл с именем Номенклатура_0034771000002395740.xml присутствует.
Если убрать фоновые задания и явно запустить процедуру копирования - то все проходит без ошибок.
(1)
Во-первых, у Вас процедура написана так, что работать будет только в винде. Смотрите про ПолучитьРазделительПутиСервера() и ПолучитьРазделительПути().
Во-вторых, есть подозрение, что у Вас мешаются в кучу клиент и сервер: файл создаётся на клиенте, а скопировать пытаетесь на сервере. Или, как минимум, путь строите на клиенте, а использовать его пытаетесь на сервере.
Запустите сервер в режиме отладки (в Сети полно указаний, как). Сделайте автоматическое подключение всего, что можно, и поставьте точку остановки в свою фоновую процедуру, оттрассируйте по шагам.
Наиболее вероятное предположение пока: фоновое задание всегда выполняется на сервере и не имеет контекста. Если Вы запускаете процедуру явно, она выполняется... На сервере или на клиенте? Контекст точно не используется? Ответы проще всего найти трассировкой.
Ошибка та же:
Ошибка при копировании файла Контрагенты_010000000052.xml в папку: D:\Temp\
{ОбщийМодуль.ИнтеграцияЕГАИС.Модуль(8492)}: Ошибка при вызове метода контекста (КопироватьФайл): Ошибка копирования файлов: Ошибка копирования файлов из 'c:\temp\Контрагенты_010000000052.xml' в 'c:\temp\Контрагенты_010000000052.xml1' : Файл не обнаружен
(4)
Не понимаю, а какая разница в каком формате сам файл? Расширение - XML. При копировании идет работа с полным именем файла. Что внутри - никак не должно влиять.
(1)
Во-первых, у Вас процедура написана так, что работать будет только в винде. Смотрите про ПолучитьРазделительПутиСервера() и ПолучитьРазделительПути().
Во-вторых, есть подозрение, что у Вас мешаются в кучу клиент и сервер: файл создаётся на клиенте, а скопировать пытаетесь на сервере. Или, как минимум, путь строите на клиенте, а использовать его пытаетесь на сервере.
Запустите сервер в режиме отладки (в Сети полно указаний, как). Сделайте автоматическое подключение всего, что можно, и поставьте точку остановки в свою фоновую процедуру, оттрассируйте по шагам.
Наиболее вероятное предположение пока: фоновое задание всегда выполняется на сервере и не имеет контекста. Если Вы запускаете процедуру явно, она выполняется... На сервере или на клиенте? Контекст точно не используется? Ответы проще всего найти трассировкой.
(5)
Работа происходит в обычном приложении. Поэтому про разделитель - не знаю насколько актуально...
Про смешение клиента и сервера мысля понятна. И мысля здравая. Но в моем тестовом примере и клиент и сервер находятся на моей локальной машине. И второй нюанс - в боевом режиме создание новых объектов тоже производится регламентным заданием, поэтому клиент здесь не задействован.
Отладка подключена, но фоновое задание не подключается :( Тут надо танцы с бубном. Наверное придется брать бубен и начинать колдовать.
Ну, вот мы и нашли Вашу проблему. Толстый клиент, когда выполняете явно и сервер, когда фоновым. Про разделитель - всегда актуально. Хотите, чтобы работало хорошо всё и всегда? Делайте всё и всегда хорошо.
Про смешение клиента и сервера мысля понятна. И мысля здравая. Н
Ну? А IMHO, это - главная Ваша проблема! Слезайте с обычного приложения, оно сильно вредит культуре программирования. А фоновые именно таковую и требуют. :-)
Отладка подключена, но фоновое задание не подключается
1) сервер запущен С ПАРАМЕТРОМ ОТЛАДКА?
2) при отладке в Конфигураторе включаете галочки "Автоматическое подключение фоновых заданий"?
Нужно И то, И другое!
Да, это все сделано. Запуск предприятия осуществляется из конфигуратора. Поэтому отладка по умолчанию включена. В сервере дебаг тоже прописан, отладка серверных процедур осуществляется. Но вот с фоновыми заданиями есть нюансы - для того, чтобы к ним подключаться, надо чтобы выполнялся ряд дополнительных условий.
Лично я знаю всего два условия... сервер в режиме отладки и автоматическое подключение фоновых заданий в конфигураторе.
ну тогда я подкину в копилку знаний - есть нюанс что база должна быть прописана так же, с точностью до символа и чуть ли не до регистра, как и на самом сервере 1С. т.е. если на сервере указан комп через IP, а на клиенте через имя машины, то отладка не сработает.
ну тогда я подкину в копилку знаний - есть нюанс что база должна быть прописана так же, с точностью до символа и чуть ли не до регистра, как и на самом сервере 1С. т.е. если на сервере указан комп через IP, а на клиенте через имя машины, то отладка не сработает.
1С 8.3.6+ - таких чудес не заметил.
Впрочем, это и не важно. Давайте стек вызовов: как вызываются Ваши процедуры и какие флажки у модуля. Попробуем сломать всё так, чтобы оно заработало! :-)
Попробуем сломать всё так, чтобы оно заработало! :-)
Спасибо за помощь и участие всем, кто помог. Изначальная проблема, как часто бывает, была по невнимательности, писано в (18) и правильно диагносцирована в (5).
Выношу на общественность новый код, защищенный от проблем клиент/сервера.
Процедура ВыгрузитьОбъектВXML(Объект, ИмяФайла, МассивПапок) Экспорт
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Объект, НазначениеТипаXML.Явное);
ОбъектСтрокой = ЗаписьXML.Закрыть();
МассивЗаданий = Новый Массив;
Для каждого ПапкаВыгрузки Из МассивПапок Цикл
МассивПараметров = Новый Массив;
МассивПараметров.Добавить(Выборка.ПапкаВыгрузки);
МассивПараметров.Добавить(ИмяФайла);
МассивПараметров.Добавить(ОбъектСтрокой);
Задание = ФоновыеЗадания.Выполнить("МодульТест.СкопироватьФайлВКаталог", МассивПараметров);
МассивЗаданий.Добавить(Задание);
//СкопироватьФайлВКаталог(Выборка.ПапкаВыгрузки, ИмяФайла, ПолноеИмяФайла); // Вариант без фоновых заданий
КонецЦикла;
КонецПроцедуры
Процедура СкопироватьФайлВКаталог(ПапкаВыгрузки, ИмяФайла, ОбъектСтрокой) Экспорт
Текст = Новый ЗаписьТекста(ПапкаВыгрузки + "\" + ИмяФайла, КодировкаТекста.UTF8);
Текст.Записать(ОбъектСтрокой);
Текст.Закрыть();
КонецПроцедуры
Процедура ЗагрузитьОбъект(ПолноеИмя)
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ПолноеИмя);
НовыйОбъект = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
НовыйОбъект.ОбменДанными.Загрузка = Истина;
НовыйОбъект.Записать();
УдалитьФайлы(ТекФайл.ПолноеИмя);
КонецПроцедуры
не все так просто! Все сделано как в тех статьях. режим дебаг включен. галка автоматическое подключение к фоновым заданиям тоже. Для примера можно в инструментах разработчика запустить выполнение фонового задания на сервере - остановка на точке останова происходит. А вот в фоновом задании - нет.
(1) попробуйте убрать запуск фонового задания из цикла. Для одной конкретной папки выгрузки сделать.
И для копирования попробуйте указывать не полный путь:
Процедура ВыгрузитьОбъектВXML() вызывается на клиенте?. А СкопироватьФайлВКаталог() вызывается на сервере? Соответственно файл должен лежать в каталоге "c:\temp\" самого сервера.
А у вас вероятнее всего он лежит в каталоге "c:\temp\" пользователя
(11) только что написали. Процедура вызывается НЕ на клиенте и НЕ на сервере, а в обычном приложении. То есть, там и то, и другое в куче.
А фоновое, естественно, только на сервере.
(16) Ну я имею ввиду что файл записывается во временный каталог ПОЛЬЗОВАТЕЛЯ под которым запущен сеанс.
А фоновое задание, поскольку выполняется на сервере, то оно ищет файл в каталоге "c:\temp\" самого сервера, файла там естественно нет.
Надо помещать файл в какой то общий сетевой каталог, к которому есть доступ как с клиентских машин, так и с сервера.
А у вас вероятнее всего он лежит в каталоге "c:\temp\" пользователя
Да, с третьего раза дошло!
Есть две базы, одна на локальном сервере, вторая на удаленном сервере! Вот тут и зарылась собака! Сейчас тестирую на удаленном сервере, поэтому действительно запись объекта производится в толстом клиенте, а фоновое задание - на сервере! Причина в этом.
Вообще, Вы, давайте, с самого начала опишите. Мне кажется, у Вас проблема растёт из того, как всё вызывается.
МодульТест какие флажки имеет?
Как сделали подключение к событию ПриЗаписи? От какого объекта: от формы, от справочника, подпиской?