Имя: Пароль:
1C
1С v8
сообщение с сервера клиенту
0 posvad
 
29.07.14
14:43
Не могу разобраться с тривиальной СообщитьПользователю().
На сервере выполняются длительные расчеты, типа несколько раз по миллиону раз 2х2. На каждом миллионе пользователю должно сообщаться, что начат следующий миллион вычислений.
Имею для этого код такого вида

&НаКлиенте
Процедура ВыполнитьРасчет(Команда)
    СерверныйРасчет();
КонецПроцедуры

&НаСервере
Процедура СерверныйРасчет()
    Сообщение = Новый СообщениеПользователю();
    Для И=0 По 10 Цикл
        Сообщение.Текст = "Итерация = " + И;
        Сообщение.Сообщить();
        Для Жи = 0 По 1000000 Цикл
            Вычислить=2*2;
        КонецЦикла;
    КонецЦикла;
КонецПроцедуры

Я так понимаю, что надо дать указание в Сообщение, на какую форму выводить сообщения, но меня перемкнуло и я никак не могу сообразить куда и какое значение подсунуть?!.
1 Otkr
 
29.07.14
14:45
На сервере нет форм
2 Фокусник
 
29.07.14
14:46
(0) Подход такой: нужно сформировать на сервере предварительную структуру (или массив), вернуть её на клиент. На клиенте перебирать эту структуру, сообщать пользователю что нужно и возвращаться на сервер за следующей итерацией и уже полным расчетом.
3 Fish
 
29.07.14
14:48
(0) Читаем СП:
"СообщениеПользователю (UserMessage)
ИдентификаторНазначения (TargetID)
Использование:

Чтение и запись.
Описание:

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

Доступность:

Тонкий клиент, веб-клиент, сервер, толстый клиент, внешнее соединение, мобильное приложение(клиент), мобильное приложение(сервер). "
4 posvad
 
29.07.14
14:48
Конечно нет. Форма на клиенте, откуда вызывалась команда. Вот и надо дать ссылку на нее с помощью параметров Сообщение.УстановитьДанные, вроде бы...
5 f_vadim
 
29.07.14
14:49
Из БП. ОбщегоНазначенияКлиентСервер

Процедура СообщитьПользователю(
        Знач ТекстСообщенияПользователю,
        Знач КлючДанных = Неопределено,
        Знач Поле = "",
        Знач ПутьКДанным = "",
        Отказ = Ложь) Экспорт
    
    Сообщение = Новый СообщениеПользователю;
    Сообщение.Текст = ТекстСообщенияПользователю;
    Сообщение.Поле = Поле;
    
    ЭтоОбъект = Ложь;
    
#Если НЕ (ТонкийКлиент ИЛИ ВебКлиент) Тогда
    Если КлючДанных <> Неопределено
       И XMLТипЗнч(КлючДанных) <> Неопределено Тогда
        ТипЗначенияСтрокой = XMLТипЗнч(КлючДанных).ИмяТипа;
        ЭтоОбъект = Найти(ТипЗначенияСтрокой, "Object.") > 0;
    КонецЕсли;
#КонецЕсли
    
    Если ЭтоОбъект Тогда
        Сообщение.УстановитьДанные(КлючДанных);
    Иначе
        Сообщение.КлючДанных = КлючДанных;
    КонецЕсли;
    
    Если НЕ ПустаяСтрока(ПутьКДанным) Тогда
        Сообщение.ПутьКДанным = ПутьКДанным;
    КонецЕсли;
        
    Сообщение.Сообщить();
    
    Отказ = Истина;
    
КонецПроцедуры

6 f_vadim
 
29.07.14
14:50
(4) в твоём случае все сообщения пользователь увидит после передачи управления на клиента.
7 f_vadim
 
29.07.14
14:51
т.е. все сразу, после окончания длительного расчёта
8 posvad
 
29.07.14
14:51
а хотелось бы иначе
9 posvad
 
29.07.14
14:51
после каждой итерации
10 f_vadim
 
29.07.14
14:52
фоновое задание или обрабатывать по частям, каждый раз возвращаясь на клиента
11 ДенисЧ
 
29.07.14
14:52
(8) Всем хочется. Только вот тупая 1с никак не хочет этого делать, сколько не проси.
12 Fish
 
29.07.14
14:53
(9) Ты уже определись: либо ты хочешь делать расчёт на сервере, либо с клиентом общаться.
13 posvad
 
29.07.14
14:54
Я хочу, чтобы клиент во время расчета не скучал
14 posvad
 
29.07.14
14:54
а почитал что-нибудь для разнообразия
15 ДенисЧ
 
29.07.14
14:54
(13) песенку ему поставь в отдельном медиаплеере.
16 f_vadim
 
29.07.14
14:55
(12) а чего плохого в том, чтоб хотеть и то, и это?

(14) ну башорг ему открывай перед запуском :)
17 Fish
 
29.07.14
14:56
(13) Покажи ему картинку ДлительнаяОперация48
18 posvad
 
29.07.14
14:56
Не конструктивно.

Так это вообще не возможно чтоли?
19 posvad
 
29.07.14
14:57
вот так пульнуть сообщение с сервера на клиента
20 ДенисЧ
 
29.07.14
14:57
(18) Тебе уже предложили два варианта. Причём вполне неглупые люди (уж поверь). Так что лучше прислушайся.
21 Fish
 
29.07.14
14:57
(18) Делай расчёт на клиенте, и показывай ему, что хошь.
22 posvad
 
29.07.14
14:58
Мда...

Либо клиента расчетами грузить, либо сетку тупым гоном данных туда - сюда...
23 Фокусник
 
29.07.14
14:59
(18) Представь. У тебя есть задача: сходить в магазин, набрать товар и сообщать о состоянии набранного товара жене.
Условия: сообщать жене можно только лично. Жена находится дома (клиент), товар набирать можно в магазине (сервер).

У тебя есть два варианта:

- Набрать в магазине (серверная процедура) всю тележку с товаром и по приходу домой сказать: "Всё набрал".

- Набрать пол тележки (на сервере), вернуться домой (на клиент) сказать "набрал 20%", вернуться в магазин (на сервер), донабрать еще товара, вернуться домой (на клиент) сказать "набрал 40%". и т.д.  Причем если таскать из магазина до дома всю тележку с товаром, то это будет лишние данные и соответственно тележку (данные) нужно будет оставлять на хранении в магазине (хранилище на сервере).

PS мобильник в магазине "не ловит", поэтому позвонить из магазина домой (передать сообщение с сервера на клиент, как ты хочешь) нельзя ;)
24 Fish
 
29.07.14
15:00
(22) Так ты в любом случае хочешь нагрузить "сетку тупым гоном данных туда - сюда". Или ты думал, что сервер сообщение телепатически передаёт?
25 Фокусник
 
29.07.14
15:00
(22) "либо сетку тупым гоном данных туда - сюда..."

Не нужно гонять данные туда-сюда, данные нужно помещать в хранилище на сервере и при следующем заходе "на сервер" данные поднимать из этого хранилища.
26 Фокусник
 
29.07.14
15:01
(23)+ "Набрать пол тележки" читать как "Набрать часть тележки" :)
27 Kamas
 
29.07.14
15:02
(23) фоновые  обработчик ожидания хранилище значений
28 posvad
 
29.07.14
15:02
Я когда иду в магазин, то набрав пол тележки, останавливаюсь, звоню по сотику и говорю "набрал 50%", а потом продолжаю набирать дальше. Но, похоже, что с не ловящим сотиком мой случай...

Буду через хранилище, спасибо.
29 f_vadim
 
29.07.14
15:03
Колбэк, я так понимаю, это когда мобила в магазине ловит :)
30 posvad
 
29.07.14
15:04
Зачем колбэк. Ведь поокончании расчета данные на форму сами возвращаются, значит сервак как -то сообщает клиенту, что он кончил...
31 posvad
 
29.07.14
15:05
а раз так, то возможность должна существовать, просто не реализована.
32 posvad
 
29.07.14
15:06
А пример с тележкой мне понравился.
33 ДенисЧ
 
29.07.14
15:06
(31) А теперь представь себе, что у тебя не просто клиент, а кеб-клиент...
34 f_vadim
 
29.07.14
15:09
(33) в js есть возможность асинхронно запулить и колбэк повесить.
35 posvad
 
29.07.14
15:10
Представил. и не вижу проблемы. AJAX как-то реализует эту функцию без проблем; пример: mail.ru itar-tass.com. Всё интерактивно через Веб.

Правда, это не совсем мой случай, там опрос через промежутки времени.
36 posvad
 
29.07.14
15:10
а в моем случае по событиям сервера
37 posvad
 
29.07.14
15:11
но как я уже писал события сервера передаются клиенту по окончании расчета
38 posvad
 
29.07.14
15:12
а значит принципиальная возможность есть
39 posvad
 
29.07.14
15:14
Ладно, пойду сдавать тележку на хранение и звонить с улицы ... 8-))
40 Kamas
 
29.07.14
15:14
(37) да только что мешает на клиенте формировать пакеты и отправлять на сервер
41 Kamas
 
29.07.14
15:15
&НаКлиенте
Процедура ВыполнитьРасчет(Команда)
Сообщение = Новый СообщениеПользователю();
    Для И=0 По 10 Цикл
        Сообщение.Текст = "Итерация = " + И;
        Сообщение.Сообщить();  
СерверныйРасчет();
КонецЦикла;
КонецПроцедуры

&НаСервере
Процедура СерверныйРасчет()
  
        Для Жи = 0 По 1000000 Цикл
            Вычислить=2*2;
        КонецЦикла;
    
КонецПроцедуры
42 Chai Nic
 
29.07.14
15:17
(41) В общем случае это не решение, а костыль. Ибо алгоритм может быть таким, что создавать отдельные итерации серверных вызовов будет невозможно или слишком затратно.
43 f_vadim
 
29.07.14
15:19
(42) согласен, проще забить на пользователя, чем городить огород.
44 Kamas
 
29.07.14
15:20
(42) ды в этом коде как раз самое и оно понятно и наглядно. А общий случай это где ?? Чет с разбегу не придумаю((
45 f_vadim
 
29.07.14
15:21
(44) тебе надо обработать 100500 записей которые тебе вернул запрос
46 Chai Nic
 
29.07.14
15:23
(44) Ну например какая-то сложная рекурсия с огромным объемом данных в памяти. И при этом оператору надо сообщать, что алгоритм не завис, а находится на таком-то этапе.
47 Kamas
 
29.07.14
16:04
(46) рекурсии использовать как раз и рекомендуют из-за огромного объема данных в памяти))а на циклы их менять ваще грех смертный
48 Kamas
 
29.07.14
16:06
(45) смотря как их обработать нужно Можно изврат и содомию всякую придумать
49 jk3
 
29.07.14
17:56
(42) Угу. Проще написать, что выполнение может занять от нескольких минут до нескольких часов =)
50 Garykom
 
гуру
29.07.14
18:14
(0) Решение ))

1. Сервер пишет % или иное по ходу выполнения куда то, куда есть доступ и серверу и клиенту (реквизит обработки, формы, параметры сеанса и прочее)

2. Клиент периодически проверят что там написал сервер и выводит, можно ОбработкаОжидания заюзать

ПРОФИТ
51 Garykom
 
гуру
29.07.14
18:15
(50)+ Эту серверную тоже через ОбработкуОжидания запускай с разовым выполнением чтобы фокус на клиента вернулся
52 Garykom
 
гуру
29.07.14
18:16
Т.е. суть:
Сервер НЕ МОЖЕТ передать что то клиенту по своему желанию!
Он ему может только ОТВЕТИТЬ на его запрос.
53 f_vadim
 
29.07.14
18:19
(52) если фоновым заданием запускать, откуда возьмётся "реквизит обработки, формы, параметры сеанса"?

так только в регистр или файл писать.
54 Garykom
 
гуру
29.07.14
18:29
(53) эээ ничего не путаем?
Не "ФоновоеЗадание" а "ОбработкаОжидания"
55 f_vadim
 
29.07.14
18:33
(54) путаем :)
надо проверить
56 ДенисЧ
 
29.07.14
18:35
(50) обработка ожидания не спасёт, если не фоновое запускать
57 Garykom
 
гуру
29.07.14
18:37
(56) вообще то даже на android в мобильном приложении работает ))
просто через Сообщить() в обработчике ожидания
58 Fragster
 
гуру
29.07.14
18:39
Фоновое задание + обработчик ожидания, который получает сообщения от фонового задания
59 f_vadim
 
29.07.14
18:42
Серверную через обработчик ожидания беспонту запускать. Оно залипает на время выполнения.
60 f_vadim
 
29.07.14
18:44
ну нафик. написал "ожидайте" и усё.
или колесо крутить как типовых отчётах.
61 Garykom
 
гуру
29.07.14
18:44
(59) гм не знаю потому что разбито на процедуры и сообщаю между ними и все ок
62 ДенисЧ
 
29.07.14
18:45
(57) не работает. Проверено
63 ДенисЧ
 
29.07.14
18:46
+62 в смысле - в десктопной 1с. Мобильную не смотрел
64 Garykom
 
гуру
29.07.14
18:48
(62)(63) Прав
а я неправ у меня &НаКлиенте оказывается выполняется, сорри
65 f_vadim
 
29.07.14
18:50
(61) ну вот я по кнопке подключаю обработчик на некую процедуру, которая вызывает серверную. она запускается, пока выполняется - клиент не шевелится.
66 Fragster
 
гуру
29.07.14
18:52
(65) делаешь фоновое. потом в обработчике ожидания делаешь

ФоновоеЗадание (BackgroundJob)
ПолучитьСообщенияПользователю (GetUserMessages)
Синтаксис:

ПолучитьСообщенияПользователю(<УдалятьПолученные>)
Параметры:

<УдалятьПолученные> (необязательный)

Тип: Булево.
Признак необходимости удаления полученных сообщений.
Истина - удалять.
Значение по умолчанию: Ложь
Возвращаемое значение:

Тип: ФиксированныйМассив.

Описание:

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

Доступность:

Сервер, толстый клиент, внешнее соединение.
67 Fragster
 
гуру
29.07.14
18:53
а в фоновом - как в (0).
по вопросу передачи данных - через ВременноеХранилище однократно
68 Fragster
 
гуру
29.07.14
18:53
Глобальный контекст.ПоместитьВоВременноеХранилище (Global context.PutToTempStorage)
Глобальный контекст (Global context)
ПоместитьВоВременноеХранилище (PutToTempStorage)
Синтаксис:

ПоместитьВоВременноеХранилище(<Данные>, <Адрес>)
Параметры:

<Данные> (обязательный)

Тип: Произвольный.
Данные, которые необходимо поместить во временное хранилище.
<Адрес> (необязательный)

Тип: УникальныйИдентификатор; Строка.
Адрес во временном хранилище, по которому надо поместить данные. Или уникальный идентификатор формы, во временное хранилище которой, надо поместить данные и вернуть новый адрес.
В случае, если передается УникальныйИдентификатор формы, то значение будет автоматически удалено после закрытия этой формы.
Если параметр не указан, помещенное значение будет удалено после очередного запроса сервера из общего модуля, при контекстном и неконтекстном серверном вызове из формы, при серверном вызове из модуля команды или при получении формы.
Возвращаемое значение:

Тип: Строка.
Если в параметре <Адрес> указан уникальный идентификатор формы, то после помещения значения во временное хранилище формы, возвращает адрес.
Данные возвращаются только после того, как фоновое задание будет завершено.
Описание:

Сохраняет сериализуемое значение во временное хранилище.

Доступность:

Тонкий клиент, веб-клиент, сервер, толстый клиент, внешнее соединение.
Примечание:

Также позволяет поместить данные из фонового задания в родительский сеанс. Для этого следует в родительском сеансе поместить во временное хранилище пустое значение, передав идентификатор формы. Затем полученный адрес передать в фоновое задание через параметры фонового задания. Далее, если этот адрес использовать в параметре <Адрес>, то результат будет скопирован в сеанс, из которого было запущено фоновое задание.
Я не хочу быть самым богатым человеком на кладбище. Засыпать с чувством, что за день я сделал какую-нибудь потрясающую вещь — вот что меня интересует. Стив Джобс