Поделиться через


Мост с существующими событиями .NET

Rx предоставляет фабричные методы для моста с существующими асинхронными источниками в .NET, чтобы можно было использовать широкие возможности создания, фильтрации и управления ресурсами, предоставляемые Rx в потоках данных любого типа. В этом разделе рассматривается оператор FromEventPattern, который позволяет "импортировать" событие .NET в Rx в качестве наблюдаемой последовательности. При каждом возникновении события в наблюдаемую последовательность будет доставляться сообщение OnNext. Затем можно управлять данными событий так же, как и любыми другими наблюдаемыми последовательностями.

Rx не направлен на замену существующих моделей асинхронного программирования, таких как события .NET, асинхронный шаблон или библиотека параллельных задач. Однако при попытке создания событий фабричные методы Rx обеспечивают удобство, которое не может быть найдено в текущей модели программирования. Это особенно актуально для обслуживания ресурсов (например, когда следует отменить подписку) и фильтрации (например, выбора типа получаемых данных). В этом и последующих разделах вы можете изучить, как эти функции Rx могут помочь в асинхронном программировании.

Преобразование события .NET в наблюдаемую последовательность Rx

В следующем примере создается простой обработчик событий .NET для события перемещения мыши и выводится расположение мыши в метке формы Windows.

using System.Linq;
using System.Windows.Forms;
using System.Reactive;
using System.Reactive.Linq;
using System;
using WinForm;
using System.Reactive.Disposables;

class Program {
 
    static void Main() 
    {
         var lbl = new Label(); 
         var frm = new Form { Controls = { lbl } }; 
         frm.MouseMove += (sender, args) =>
         {
              lbl.Text = args.Location.ToString();
         };
         Application.Run(frm);
    }; 
}

Чтобы импортировать событие в Rx, можно использовать оператор FromEventPattern и предоставить объекты EventArgs, которые будут вызваны связующим событием. Оператор FromEventPattern работает с событиями, которые принимают отправителя объекта и некоторые EventArgs, и использует отражение для поиска этих методов добавления и удаления. Затем данное событие преобразуется в наблюдаемую последовательность с типом EventPattern, который захватывает как отправитель, так и аргументы события.

Для делегатов, имеющих один параметр (нестандартные события), можно использовать оператор FromEvent, который принимает пару функций, используемых для присоединения и отсоединения обработчика.

В следующем примере мы преобразуем поток событий перемещения мыши формы Windows в наблюдаемую последовательность. При каждом срабатывании события перемещения мыши подписчик будет получать уведомление OnNext. Затем мы можем проверить значение EventArgs такого уведомления и получить расположение перемещения мыши.

using System.Linq;
using System.Windows.Forms;
using System.Reactive;
using System.Reactive.Linq;
using System;
using WinForm;
using System.Reactive.Disposables;

class Program {
 
    static void Main() 
    {
         var lbl = new Label(); 
         var frm = new Form { Controls = { lbl } }; 
         IObservable<EventPattern<MouseEventArgs>> move = Observable.FromEventPattern<MouseEventArgs>(frm, "MouseMove");
         move.Subscribe(evt => { 
                             lbl.Text = evt.EventArgs.Location.ToString(); 
                       }) ;
         Application.Run(frm);
   }; 
}

Обратите внимание, что в этом примере становится наблюдаемой последовательностью, move в которой можно управлять дальше. В разделе Запрос наблюдаемых последовательностей с помощью операторов LINQ показано, как проецируете эту последовательность в коллекцию типа Points и отфильтруйте ее содержимое, чтобы приложение получало только значения, удовлетворяющие определенным критериям.

Очистка обработчика событий выполняется объектом IDisposable, возвращаемым методом Subscribe. Вызов Dispose (который выполняется путем достижения конца блока using в этом примере) приведет к освобождению всех ресурсов, используемых последовательностью, включая базовый обработчик событий. Это, по сути, отвечает за отмену подписки на событие от вашего имени.

См. также:

Основные понятия

Запрос наблюдаемых последовательностей с помощью операторов LINQ