Skip to content

Реактивное программирование на C# с помощью Rx на примере СЭД

Введение

Как написано в статье про реактивные расширения [1], «если есть некий процесс, который может выполняться долго и возвращать несколько промежуточных результатов с течением времени», то реактивные расширения это именно то, что вам нужно.  Поэтому давайте попробуем разобраться в этом вопросе и понять для чего это нужно.

Вспомним как работает клиент-серверная архитектура. Клиент отправляет запрос серверу и получает ответ, так в чём же проблема? Чтобы понять в чём проблема нужно вспомнить как работают приложения, не важно это приложение под desktop или web. Когда приложение запускается, то запускается процесс от рисовки окон или форм данного приложения, этот процесс выполняется всегда пока приложение не будет завершено.

При отображении элементов форм выполняются действия, которые отслеживают реакцию пользователя. Но что произойдёт если пользователь запустит действие, которое требует длительное время? В этом случае приложение останавливает свою работу.

Подумаем какие есть пути решения этой проблемы.

Почему бы не запустить ещё один процесс?

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

Возникает вопрос, можно ли обойтись одним процессом и решить проблему блокировки выполнения. Оказывается это возможно.

Что можно сделать в одном процессе?

Ответ на этот вопрос прост. Нужно просто прекратить ждать и делать, в этот момент что-нибудь ещё (например продолжить процесс перерисовки элементов формы). Или другими словами рационально распределить ресурсы процессора в пределах одного потока.

Пример асинхронной загрузки данных

Примером асинхронной загрузки данных может служить система электронного документооборота (СЭД)Pilot-ICE [2].

Сервер выполняет запрос к серверу и ожидает получение данных, для выполнения таких запросов используется класс, унаследованный от интерфейса IObserver<T>. Для этого с помощью метода Subscribe(this) выполняем подписку на экземпляр данного класса и получаем результат выполнения с помощью метода OnNext нашего класса.

Данный путь понятен, но можно ли его упросить? Да можно, используя The Reactive Extensions for .NET, который позволяет получить объект в функциональном стиле одной командой:

var nodes = await _repository.AsyncMethods().GetObjectsAsync(ids, (o) => new DataObject(o), _cts.Token);

Ссылки

  1. Пишите чистый код с Реактивными Расширениями (Reactive Extensions): https://habrahabr.ru/post/242613/
  2. Pilot-ICE: http://pilotems.com/
  3. Центр загрузок системы Pilot: https://pilot.ascon.ru/
  4. Bing it on, Reactive Extensions! – story, code and slides. Andrei Rinea’s technical blog: http://blog.andrei.rinea.ro/2013/06/01/bing-it-on-reactive-extensions-story-code-and-slides/
  5. https://rehansaeed.com/reactive-extensions-part1-replacing-events/
  6. The Reactive Extensions for .NET — http://reactivex.io, https://github.com/dotnet/reactive
Добавить комментарий