Имя: Пароль:
1C
1С v8
Зависание 1С при возврате на клиента
0 non1ka
 
10.02.15
14:05
Добрый день.
Платформа 8.3.5.1443. Модуль собственной разработки.

Ошибка в следующем, в определенной ситуации (не диагностируемой), после выполнения процедуры &НаСервереБезКонтекста, которая возвращает «массив структур» для дальнейшего заполнения табличной части справочника  в момент когда производится отключение от сервера (КонецФункции) и возврат НаКлиента система «мифически» зависает и не передает управление Клиенту. Другими словами система зависает.

В некоторых справочниках все отлично, в некоторых зависает.

Что я предпринял:
1. Вынес все выводы сообщений из процедуры;
2. Вывел из контекста формы, перенес НаСерверБезКонтекста, ранее заполнял табличную часть в процедуре &НаСервере методом Загрузить();
3. Установил привилегированный режим.

Укажите куда копать?
1 mikecool
 
10.02.15
14:06
замер производительности
2 H A D G E H O G s
 
10.02.15
14:07
(0) Циклическая ссылка?
3 polosov
 
10.02.15
14:09
(0) А в структуре значения каких типов?
4 Жан Пердежон
 
10.02.15
14:10
(0) но код нам все равно не покажешь?
5 non1ka
 
10.02.15
14:12
Обнаружил зависимость.
Зависит от размера массива.
В диспетчере состояние процесса "Работает".

Код простой:


УстановитьПривилегированныйРежим(Истина);
    
    ТабличнаяЧастьСоставМеню = ПолучитьИзВременногоХранилища(АдресВоВременномХранилище);
    ТабличнаяЧастьСоставМенюДляРазузлования = ТабличнаяЧастьСоставМеню.Скопировать();
    ТабличнаяЧастьСоставМенюДляРазузлования.Свернуть("Номенклатура, ЕдиницаИзмерения");
    
    ТаблицаМатериалов = ИнициализироватьТаблицуМатериаловПоПродукции();
    МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
    
    // Сформируем таблицу материалов по продукции, для оперделения закупочной стоимости
    Запрос = Новый Запрос;
    Запрос.УстановитьПараметр("ТабличнаяЧастьСоставМеню", ТабличнаяЧастьСоставМеню);
    Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
    Запрос.Текст = ПолучитьТекстЗапросаИнициированияВременныхТаблицОбновленияСтоимости();
    Запрос.Выполнить();
    
    // Выполним рекурсивное заполнение таблицы материалы по продукции
    Для каждого СтрокаТабличнойЧастиСоставМеню из ТабличнаяЧастьСоставМенюДляРазузлования Цикл
        
        Если СтрокаТабличнойЧастиСоставМеню.Номенклатура.Пустая() Тогда
            Продолжить;
        КонецЕсли;
        
        Запрос.Текст = ПолучитьТекстЗапросаОпределенияОсновнойСпецификацииПродукции();
        Запрос.УстановитьПараметр("Номенклатура", СтрокаТабличнойЧастиСоставМеню.Номенклатура);
        
        РузельтатЗапросаПоискаОснонойСпецификации = Запрос.Выполнить();
        Если РузельтатЗапросаПоискаОснонойСпецификации.Пустой() Тогда
            Продолжить;
        КонецЕсли;    
        
        ВыборкаПоискаОснонойСпецификации = РузельтатЗапросаПоискаОснонойСпецификации.Выбрать();
        ВыборкаПоискаОснонойСпецификации.Следующий();
        
        Если СписокСпецификацийДляАнализа.НайтиПоЗначению(ВыборкаПоискаОснонойСпецификации.Спецификация) = Неопределено Тогда
            СписокСпецификацийДляАнализа.Добавить(ВыборкаПоискаОснонойСпецификации.Спецификация);
        КонецЕсли;
        
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // UIK KAV ++
        // PR_ДополнительныйМодуль.ПодпискаНаСобытиеПередЗаписьюСпецификацииНоменклатуры(ВыборкаПоискаОснонойСпецификации.Спецификация, Ложь);
        // UIK KAV --
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        
        ПараметрыПоиска = Новый Структура;
        ПараметрыПоиска.Вставить("Продукция", СтрокаТабличнойЧастиСоставМеню.Номенклатура);
        ПараметрыПоиска.Вставить("Спецификация", ВыборкаПоискаОснонойСпецификации.Спецификация);
        ПараметрыПоиска.Вставить("ЕдиницаИзмеренияПродукции", СтрокаТабличнойЧастиСоставМеню.ЕдиницаИзмерения);
        ПараметрыПоиска.Вставить("КоличествоПродукции", 1);
        
        ПараметрыЗаполнения = Новый Структура;
        ПараметрыЗаполнения.Вставить("Продукция", СтрокаТабличнойЧастиСоставМеню.Номенклатура);
        ПараметрыЗаполнения.Вставить("ЕдиницаИзмеренияПродукции", СтрокаТабличнойЧастиСоставМеню.ЕдиницаИзмерения);
        
        // Проверим, может быть мы уже расчитывали стоимость по номенклатуре
        ПараметрыПроверкиРасчетаПродукции = Новый Структура("Продукция, ЕдиницаИзмеренияПродукции");
        ЗаполнитьЗначенияСвойств(ПараметрыПроверкиРасчетаПродукции, ПараметрыЗаполнения);
        Если ТаблицаМатериалов.НайтиСтроки(ПараметрыПроверкиРасчетаПродукции).Количество() Тогда
            Продолжить;
        КонецЕсли;
        
        ВыполнитьРекурсивноеЗаполнениеТаблицыМатериалов(ТаблицаМатериалов, ПараметрыПоиска, ПараметрыЗаполнения, МенеджерВременныхТаблиц, СписокСпецификацийДляАнализа);
        
    КонецЦикла;
    
    Запрос.УстановитьПараметр("ТаблицаМатериалов", ТаблицаМатериалов);
    Запрос.Текст = ПолучитьТекстЗапросаОбновленияСебестоимости();
    ТабличнаяЧастьСоставМеню = Запрос.Выполнить().Выгрузить();
    
    // Уничтожим менеджер временных таблиц
    МенеджерВременныхТаблиц = Неопределено;
    
    МассивСтрокРасчетаРозничнойСтоимости = ТабличнаяЧастьСоставМеню.НайтиСтроки(Новый Структура("МетодРасчетаСтоимости", "ФормулаРасчета"));
    Для каждого СтрокаМассиваРасчетаРозничнойСтоимости из МассивСтрокРасчетаРозничнойСтоимости Цикл
        
        Попытка    
            ФормулаРасчетаСтоимости = СтрЗаменить(СтрокаМассиваРасчетаРозничнойСтоимости.ФормулаРасчетаСтоимости, "Себестоимость", СтрЗаменить(СтрокаМассиваРасчетаРозничнойСтоимости.Себестоимость, ",", "."));
            ФормулаРасчетаСтоимости = "СтрокаМассиваРасчетаРозничнойСтоимости.Стоимость = " + ФормулаРасчетаСтоимости;
            Выполнить(ФормулаРасчетаСтоимости);
        Исключение
        КонецПопытки;
        
    КонецЦикла;
    
    КлючиСтруктурыИзКолонок = "";
    Для каждого КолонкаТабличнойЧастиСоставМеню из ТабличнаяЧастьСоставМеню.Колонки Цикл
        КлючиСтруктурыИзКолонок = КлючиСтруктурыИзКолонок
        + ?(Не ТабличнаяЧастьСоставМеню.Колонки.Индекс(КолонкаТабличнойЧастиСоставМеню), "",
          ?(ТабличнаяЧастьСоставМеню.Колонки.Индекс(КолонкаТабличнойЧастиСоставМеню) = ТабличнаяЧастьСоставМеню.Колонки.Количество() - 1, "", ","))
        + КолонкаТабличнойЧастиСоставМеню.Имя;
    КонецЦикла;
    
    МассивСтруктурСОбновленнойСебестоимостью = Новый Массив;
    Для каждого СтрокаТабличнойЧастиСоставМеню из ТабличнаяЧастьСоставМеню Цикл
        СтруктураВМассив = Новый Структура(КлючиСтруктурыИзКолонок);
        ЗаполнитьЗначенияСвойств(СтруктураВМассив, СтрокаТабличнойЧастиСоставМеню);
        МассивСтруктурСОбновленнойСебестоимостью.Добавить(СтруктураВМассив);
    КонецЦикла;
    
    УстановитьПривилегированныйРежим(Ложь);
    
    Возврат МассивСтруктурСОбновленнойСебестоимостью;
6 DmitrO
 
10.02.15
14:21
Функция ВызватьПереполнениеСтека()
   Массив = Новый Массив;
   Массив.Добавить(Массив);
   Возврат Массив;
КонецФункции
7 non1ka
 
10.02.15
14:55
Самое удивительное, что в тонком клиенте работает все отлично.
8 НЕА123
 
10.02.15
15:30
(5)
может мимо, но...

попробовать присвоить

>Запрос.Выполнить();


ПУСТО = Запрос.Выполнить();
9 non1ka
 
10.02.15
16:50
Сейчас в другой процедуре, такая же проблема.

Интересный факт.
Я процедуру вынес на обработчик ожидания.
Если в процессе отладки прохожу подключение обработчика ожидания, все отрабатывает отлично. Ставлю 10 сек, что бы увидеть задержку и результат.
А если отключаю точки остановы, при подключении отладчика зависает.
10 non1ka
 
11.02.15
08:09
Ап
11 stonewolf
 
11.02.15
11:19
Попробуй вернуть как строку через ЗначениеВСтрокуВнутр.
12 non1ka
 
12.02.15
13:27
Первоначально не было ни каких возвратов. С сервера, все равно зависало.
13 non1ka
 
13.02.15
19:00
Ап!
Коллеги подскажите куда еще можно обратиться?
14 Sol78
 
13.02.15
19:32
(13)  покажи как выглядит описание функции, а то ты только её код привел
15 non1ka
 
15.02.15
14:12
(14), Что значит описание функции?

1. Табличная часть предварительно выгружается в таблицу значений и помещается во временное хранилище.
2. Вызывается серверная вне контекстная процедура которая получает из хранилища эту таблицу значений и передает ее в запрос.
3. Инициализируются временные таблицы, в которые помещаются состав спецификаций, последняя закупочная стоимость материалов, цены номенклатуры и т.п.;
4. Затем в цикле рекурсивно производится разузлование продукции до материалов (что бы определить плановую себестоимость номенклатуры на текущий момент времени).
5. Затем таблица материалов соединяется с таблицей себестоимости,
6. Затем по произвольной формуле (которую задает пользователь) рассчитывается розничная стоимость продукции.
7. Затем итоговая таблица переводится в массив структур и возвращается на клиента.

Ошибок в алгоритме нет, есть контрольные процедуры проверки рекурсии и зацикливания, все временные таблицы проиндексированы, при выполнении алгоритма зависаний нет. Всегда алгоритм завершается на КонецФункции.
16 hhhh
 
15.02.15
14:40
так вроде нельзя писать

СтруктураВМассив = Новый Структура(КлючиСтруктурыИзКолонок);

Во всех строках массива будет одна и та же структура.
17 alle68
 
15.02.15
15:01
(0) Если заполнять ТЧ на сервере, какова реакция системы?
(16) Для каждой строки своя структура.
18 non1ka
 
15.02.15
16:06
(17) Если заполнять ТЧ на сервере, какова реакция системы?

Все прекрасно выполняется, табличная часть загружается. Но при возврате на клиента система зависает.

Иногда, система не зависает и передает управление клиенту :)
Но потом вызывается процедура расчета итогов, и при возврате на клиента опять зависает :)
19 alle68
 
15.02.15
16:13
(18) А итоги тут при чём, это же справочник?
А сразу всё рассчитать на сервере нельзя, а не гонять туда-сюда?
И что значит "иногда", это зависит от настроения клиента или от положения звёзд?
20 non1ka
 
15.02.15
16:21
В справочнике, табличная часть представлена в виде ДереваЗначений, заполнение дерева значений из табличной части и расчет итогов (по каждой строке группировки) производится в отдельной процедуре, которая вызывается, как при открытии формы, так и при обновлении себестоимости.

Вот так выглядит форма справочника https://www.dropbox.com/s/oac4277zr3geqmr/Скриншот%202015-02-15%2016.18.06.png?dl=0

Скорее всего от положения звезд :) Закономерность не выявлена, открываешь форму запускаешь - отрабатывает, запускаешь снова - зависает.

Кстати, в Файловом режиме все работает стабильно.
21 alle68
 
15.02.15
16:34
(20) Значит, итоги на клиенте считать надо.
На картинке их что-то не видно...
22 non1ka
 
15.02.15
17:04
(21) Просто скриншот сделан из чистой базы данных без документов.

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

И мы проводили работы по копированию таблицы конфигурации из бэкапов средствами SQL.

Соответственно мы попытались исключить ошибки связанные с базой данных, сделали чистый cf файл, создали чистую базу данных и перенесли в нее справочники.

(21) "Значит, итоги на клиенте считать надо"
Процедура расчета итогов запускается так же при открытии формы, и в 100% случаев выполняется.

Зависания начали происходить совершенно в разных ситуациях, к примеру сейчас зависает функция подбора номенклатуры, которая открывает специализированную форму подбора, которая заполняется по такому же принципу:

1. Запрос для определения номенклатуры;
2. Загрузка номенклатуры в дерево значений
3. Возврат на клиента. (Зависает при возврате на клиента)
23 Sol78
 
16.02.15
01:53
(15)  
Функция ЭтоМояЗависающаяФункция(параметр1, Знач Параметр2, Параметр3 = Ложь)

и какие типы у параметров
24 GROOVY
 
16.02.15
02:44
Да. Об этом собственно и рекомендация 1с, не стоит имитировать работу обычного приложения в управляемом. Данные либо порционно сериализуются и самой системой отправляются клиенту, либо используется (в разумных пределах) временное хранилище.
25 H A D G E H O G s
 
16.02.15
03:11
(20) Жесть, как она есть.
26 H A D G E H O G s
 
16.02.15
03:12
(20) Завтра стукни мне в аську, я тебе все растолкую.
27 non1ka
 
17.02.15
09:33
(24) Павел, добрый день.
Если Вы меня помните, на Вашем форуме обсуждали запрет использования Регистров накопления при решении расчетных задач к Специалисту 1С. :)

В Моем случае, происходит имитирование управляемого приложения в обычном.

Но проблема не в имитировании, так как процедура зависает и в управляемом приложении!

(23) Один параметр АдресВоВременномХранилище - Адрес таблицы значений во временном хранилище.
2 + 2 = 3.9999999999999999999999999999999...