Когда необходимо производить обработку множетсва интернет-ресурсов (сайтов, web-сервисов и т.д.) , то остро встает проблема с производительностью приложения, так как при синхронных запросах время работы линейно зависит от количества запросов. Общее затраченное время на получение ресурса можно сократить если использовать параллельную обработку ресурсов.
Один из вариантов решения задачи - это использование под Windows com-объекта Msxml2.ServerXMLHTTP, он позволяет производить асинхронное получение данных после запроса ресурса. Данный объект после получения данных может вызывать callback-фукнцию однако на чистом 1С мне не удалось ее запусить, но данный com-объект позволяет с помощью метода waitForResponse приостанавливать выполнение асинхронной операции ожидая завершения операции, вот этим и воспользуемся организовав тем самым подобие polling (частые опросы). Однако о чистой асинхронности говорить не приходится, так как работа пользователя будет заблокированна на время обработки ресурсов.
Рассмотрим на основе Msxml2.ServerXMLHTTP пример опроса 30-и страниц статей с сайта microsoft.com, начиная со статьи про Msxml2.ServerXMLHTTP. Все дальнейшие рассуждения верны и для WinHttp.WinHttpRequest.
Подготовка:
Объекты = Новый Массив;
КоличествоОбъектов = 30;
Для ин = 0 По КоличествоОбъектов-1 Цикл
ОбъектHTTP = Новый COMОбъект("Msxml2.ServerXMLHTTP.6.0");
// таймаут 30 сек по всем операциям
ОбъектHTTP.setTimeouts(30000,30000,30000,30000);
// третий параметр указывает на асинхронность вызова
ОбъектHTTP.open("GET", "https://msdn.microsoft.com/ru-ru/library/ms" + Формат(762278 + ин, "ЧГ=") + "(v=vs.85).aspx", Истина);
// отправляем запрос
ОбъектHTTP.send();
// сохраняем данные
Данные = Новый Структура("Объект, Выполнено, Ошибка", ОбъектHTTP, Ложь, Ложь);
Объекты.Добавить(Данные);
КонецЦикла;
Далее запускаем цикл опроса созданных объектов, время ожидания для метода waitForResponse выбрано произвольным образом, очевидно, что оно не должно быть большим, иначе потеряем всю выгоду:
Пока Истина Цикл
ОбработаноОбъектов = 0;
Для ин = 0 По КоличествоОбъектов-1 Цикл
Если Объекты[ин].Выполнено = Ложь И Объекты[ин].Ошибка = Ложь Тогда
// readyState = 4 - признак того, что страница загружена полностью
Если (Объекты[ин].Объект.readyState <> 4) Тогда
Попытка
// время ожидания
Объекты[ин].Объект.waitForResponse(50);
Исключение
// наиболее вероятная ошибка - сработал таймаут
Объекты[ин].Ошибка = Истина;
КонецПопытки;
Иначе
// результат получен
Объекты[ин].Выполнено = Истина;
КонецЕсли;
Иначе
ОбработаноОбъектов = ОбработаноОбъектов + 1;
КонецЕсли;
КонецЦикла;
// выходим из цикла, так как все запросы обработаны
Если ОбработаноОбъектов = КоличествоОбъектов Тогда
Прервать;
КонецЕсли;
КонецЦикла
Пример реализации для WinHttpRequest, ключевое отличие в том, что в нем нет параметра readyState, результат операции возвращает метод WaitForResponse.
Для ин = 0 По КоличествоОбъектов-1 Цикл
ОбъектHTTP = Новый COMObject("WinHttp.WinHttpRequest.5.1");
ОбъектHTTP.Open("GET", "https://msdn.microsoft.com/ru-ru/library/ms" + Формат(762278 + ин, "ЧГ=") + "(v=vs.85).aspx", 1);
ОбъектHTTP.Send();
ОбъектHTTP.SetTimeouts(30000, 30000, 30000, 30000);
Данные = Новый Структура("Объект, Выполнено, Ошибка", ОбъектHTTP, Ложь, Ложь);
Объекты.Добавить(Данные);
КонецЦикла;
// ожидание ответов
Пока Истина Цикл
ОбработаноОбъектов = 0;
Для ин = 0 По КоличествоОбъектов-1 Цикл
Если Объекты[ин].Выполнено = Ложь И Объекты[ин].Ошибка = Ложь Тогда
Результат = Ложь;
Попытка
// время ожидания, в данном случае не существенно
Результат = Объекты[ин].Объект.WaitForResponse(50);
Исключение
// наиболее вероятная ошибка - сработал таймаут
Объекты[ин].Ошибка = Истина;
КонецПопытки;
Если Результат = Истина Тогда
// результат получен
Объекты[ин].Выполнено = Истина;
КонецЕсли;
Иначе
ОбработаноОбъектов = ОбработаноОбъектов + 1;
КонецЕсли;
КонецЦикла;
Если ОбработаноОбъектов = КоличествоОбъектов Тогда
Прервать;
КонецЕсли;
КонецЦикла;
Результаты: при синхронной работе (3-ий параметр Ложь в функции open) получаем 42 сек, при параллельной работе получаем 3 сек. Результаты ответов одинаковые.