Простая аналогия
Представьте, что вы повар на кухне:
-
Синхронный код — вы варите суп, стоите и ждете пока он сварится, не делая ничего другого
-
Асинхронный код — вы поставили суп вариться, и пока он готовится, режете салат
Оповещение() — синхронный подход
bsl&НаКлиенте Процедура СинхроннаяОбработка(Кнопка) // Интерфейс "зависнет" на 5 секунд! Сообщить("Начали обработку..."); // Долгая операция - пользователь не может ничего делать ВыполнитьДолгуюОперацию(); Сообщить("Обработка завершена!"); // Выведется только через 5 секунд КонецПроцедуры &НаСервере Процедура ВыполнитьДолгуюОперацию() // Имитация долгой операции Для Сч = 1 По 5000000 Цикл // Какие-то вычисления... КонецЦикла; КонецПроцедуры
Проблема: Пока выполняется ВыполнитьДолгуюОперацию(), пользователь видит "не отвечает" и не может работать с программой.
ВыполнитьОбработкуОповещения() — асинхронный подход
bsl&НаКлиенте Процедура АсинхроннаяОбработка(Кнопка) Сообщить("Начали обработку..."); // Запускаем операцию асинхронно Оповещение = Новый ОписаниеОповещения("ОбработкаЗавершена", ЭтотОбъект); ВыполнитьОбработкуОповещения(Оповещение, ЭтотОбъект); // Этот код выполнится СРАЗУ, не дожидаясь окончания обработки Сообщить("Обработка запущена, можно продолжать работу!"); КонецПроцедуры // Этот метод вызовется, когда фоновая обработка завершится &НаКлиенте Процедура ОбработкаЗавершена() Экспорт Сообщить("Фоновая обработка завершена!"); // Обновляем интерфейс, показываем результаты КонецПроцедуры
Преимущество: Интерфейс не блокируется, пользователь может продолжать работу!
Практический пример: загрузка данных
Синхронный вариант (плохо)
bsl&НаКлиенте Процедура ЗагрузитьДанныеСинхронно(Кнопка) Элементы.Статус.Заголовок = "Загрузка..."; // Интерфейс зависнет на время загрузки Данные = ЗагрузитьБольшиеДанныеССервера(); ЗаполнитьТаблицу(Данные); Элементы.Статус.Заголовок = "Загрузка завершена"; КонецПроцедуры
Асинхронный вариант (хорошо)
bsl&НаКлиенте Процедура ЗагрузитьДанныеАсинхронно(Кнопка) Элементы.Статус.Заголовок = "Загрузка..."; Элементы.КнопкаЗагрузить.Доступность = Ложь; // Запрещаем повторный запуск // Запускаем асинхронно Оповещение = Новый ОписаниеОповещения("ЗагрузкаЗавершена", ЭтотОбъект); ВыполнитьОбработкуОповещения(Оповещение, ЭтотОбъект); КонецПроцедуры &НаКлиенте Процедура ЗагрузкаЗавершена() Экспорт Данные = ЗагрузитьБольшиеДанныеССервера(); ЗаполнитьТаблицу(Данные); Элементы.Статус.Заголовок = "Загрузка завершена"; Элементы.КнопкаЗагрузить.Доступность = Истина; // Разрешаем снова КонецПроцедуры
Передача параметров в асинхронные обработчики
bsl&НаКлиенте Процедура ЗапуститьОбработкуСПараметрами(Кнопка) Параметры = Новый Структура; Параметры.Вставить("НачальнаяДата", Элементы.НачальнаяДата.Значение); Параметры.Вставить("КонечнаяДата", Элементы.КонечнаяДата.Значение); // Передаем параметры через оповещение Оповещение = Новый ОписаниеОповещения("ОбработкаСПараметрамиЗавершена", ЭтотОбъект, Параметры); ВыполнитьОбработкуОповещения(Оповещение, ЭтотОбъект); КонецПроцедуры &НаКлиенте Процедура ОбработкаСПараметрамиЗавершена(Параметры) Экспорт // Получаем переданные параметры НачальнаяДата = Параметры.НачальнаяДата; КонечнаяДата = Параметры.КонечнаяДата; Сообщить("Обрабатываем период: " + НачальнаяДата + " - " + КонечнаяДата); КонецПроцедуры
Сравнительная таблица
| Критерий | Оповещение() | ВыполнитьОбработкуОповещения() |
|---|---|---|
| Блокировка интерфейса | Да | Нет |
| Сложность реализации | Просто | Сложнее |
| Когда использовать | Быстрые операции | Долгие операции |
| Передача параметров | Нет | Да |
| Производительность | Низкая | Высокая |
Частые ошибки
Ошибка 1: Попытка обновить интерфейс из фонового потока
bsl// НЕПРАВИЛЬНО! &НаКлиенте Процедура ФоноваяОбработка() Экспорт // Этот код выполняется в фоне Элементы.Поле.Значение = "Новое значение"; // ОШИБКА! КонецПроцедуры // ПРАВИЛЬНО &НаКлиенте Процедура ФоноваяОбработка() Экспорт // Выполняем вычисления в фоне... Результат = СложныеВычисления(); // А обновление интерфейса делаем через новое оповещение Оповещение = Новый ОписаниеОповещения("ОбновитьИнтерфейс", ЭтотОбъект, Результат); ВыполнитьОбработкуОповещения(Оповещение); КонецПроцедуры
Ошибка 2: Неправильное описание оповещения
bsl// НЕПРАВИЛЬНО - не указан контекст Оповещение = Новый ОписаниеОповещения("МояПроцедура"); // ПРАВИЛЬНО Оповещение = Новый ОписаниеОповещения("МояПроцедура", ЭтотОбъект);
Когда что использовать?
Используйте Оповещение() когда:
-
Операция выполняется меньше 0.5 секунды
-
Нужен простой и понятный код
-
Работаете с небольшими объемами данных
Используйте ВыполнитьОбработкуОповещения() когда:
-
Операция занимает больше 1 секунды
-
Работаете с большими данными или сложными расчетами
-
Важно не блокировать интерфейс для пользователя
Золотое правило: Если пользователь успевает заметить "зависание" — переходите на асинхронность!
