Учебники

F # — События

События позволяют классам отправлять и получать сообщения между собой.

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

Объекты общаются друг с другом посредством синхронной передачи сообщений.

События привязаны к другим функциям; объекты регистрируют функции обратного вызова для события, и эти обратные вызовы выполняются, когда (и если) событие запускается каким-либо объектом.

Класс события и модуль события

Класс Control.Event <‘T> помогает в создании наблюдаемого объекта или события.

У него есть следующие члены экземпляра для работы с событиями —

член Описание
Публиковать Публикует наблюдение как первоклассное значение.
Спусковой крючок Запускает наблюдение с использованием заданных параметров.

Модуль Control.Event предоставляет функции для управления потоками событий —

Значение Описание
добавить: (‘T → единица) → Событие <‘ Del, ‘T> → единица Запускает данную функцию каждый раз, когда происходит указанное событие.
выберите: (опция ‘T →’ U) → IEvent <‘Del,’ T> → IEvent <‘U> Возвращает новое событие, которое запускается при выборе сообщений из исходного события. Функция выбора переводит исходное сообщение в необязательное новое сообщение.
фильтр: (‘T → bool) → IEvent <‘ Del, ‘T> → IEvent <‘ T> Возвращает новое событие, которое прослушивает исходное событие и запускает результирующее событие, только когда аргумент события передает заданную функцию.
карта: (‘T →’ U) → IEvent <‘Del,’ T> → IEvent <‘U> Возвращает новое событие, которое передает значения, преобразованные данной функцией.
объединить: IEvent <‘Del1,’ T> → IEvent <‘Del2,’ T> → IEvent <‘T> Запускает выходное событие при срабатывании любого из входных событий.
попарно: IEvent <‘Del,’ T> → IEvent <‘T *’ T> Возвращает новое событие, которое срабатывает при втором и последующем срабатывании входного события. N-й триггер входного события передает аргументы от N-1-го и N-го триггеров в виде пары. Аргумент, переданный в N-1-й запуск, удерживается в скрытом внутреннем состоянии до тех пор, пока не произойдет N-й запуск.
раздел: (‘T → bool) → IEvent <‘ Del, ‘T> → IEvent <‘ T> * IEvent <‘T> Возвращает новое событие, которое прослушивает исходное событие и запускает первое результирующее событие, если применение предиката к аргументам события вернуло true, и второе событие, если оно вернуло false.
сканирование: (‘U →’ T → ‘U) →’ U → IEvent <‘Del,’ T> → IEvent <‘U> Возвращает новое событие, состоящее из результатов применения данной функции накопления к последовательным значениям, сработавшим во входном событии. Элемент внутреннего состояния записывает текущее значение параметра состояния. Внутреннее состояние не блокируется во время выполнения функции накопления, поэтому следует позаботиться о том, чтобы вход IEvent не запускался несколькими потоками одновременно.
split: (‘T → Choice <‘ U1, ‘U2>) → IEvent <‘ Del, ‘T> → IEvent <‘ U1> * IEvent <‘U2> Возвращает новое событие, которое прослушивает исходное событие и запускает первое результирующее событие, если приложение функции к аргументам события вернуло Choice1Of2, и второе событие, если оно возвращает Choice2Of2.

Создание событий

События создаются и используются через класс Event . Конструктор Event используется для создания события.

пример

type Worker(name : string, shift : string) =
   let mutable _name = name;
   let mutable _shift = shift;
   let nameChanged = new Event<unit>() (* creates event *)
   let shiftChanged = new Event<unit>() (* creates event *)

   member this.Name
      with get() = _name
      and set(value) = _name <- value

   member this.Shift
      with get() = _shift
      and set(value) = _shift <- value

После этого вам нужно выставить поле nameChanged как открытый член, чтобы слушатели могли подключиться к событию, для которого вы используете свойство Publish события —

type Worker(name : string, shift : string) =
   let mutable _name = name;
   let mutable _shift = shift;

   let nameChanged = new Event<unit>() (* creates event *)
   let shiftChanged = new Event<unit>() (* creates event *)

   member this.NameChanged = nameChanged.Publish (* exposed event handler *)
   member this.ShiftChanged = shiftChanged.Publish (* exposed event handler *)

   member this.Name
      with get() = _name
      and set(value) = _name <- value
      nameChanged.Trigger() (* invokes event handler *)

   member this.Shift
      with get() = _shift
      and set(value) = _shift <- value
   shiftChanged.Trigger() (* invokes event handler *)

Затем вы добавляете обратные вызовы к обработчикам событий. Каждый обработчик событий имеет тип IEvent <‘T>, который предоставляет несколько методов:

метод Описание
val Добавить: event 🙁 ‘T → unit) → unit Подключает функцию слушателя к событию. Слушатель будет вызван при возникновении события.
val AddHandler: ‘del → unit Соединяет объект делегата обработчика с событием. Обработчик может быть позже удален с помощью RemoveHandler. Слушатель будет вызван при возникновении события.
val RemoveHandler: ‘del → unit Удаляет делегат слушателя из хранилища слушателей событий.

В следующем разделе приведен полный пример.

пример

Следующий пример демонстрирует концепцию и методы, обсужденные выше —

Live Demo

type Worker(name : string, shift : string) =
   let mutable _name = name;
   let mutable _shift = shift;

   let nameChanged = new Event<unit>() (* creates event *)
   let shiftChanged = new Event<unit>() (* creates event *)

   member this.NameChanged = nameChanged.Publish (* exposed event handler *)
   member this.ShiftChanged = shiftChanged.Publish (* exposed event handler *)

   member this.Name
      with get() = _name
      and set(value) = 
         _name <- value
         nameChanged.Trigger() (* invokes event handler *)

   member this.Shift
      with get() = _shift
      and set(value) = 
         _shift <- value
         shiftChanged.Trigger() (* invokes event handler *)

let wk = new Worker("Wilson", "Evening")
wk.NameChanged.Add(fun () -> printfn "Worker changed name! New name: %s" wk.Name)
wk.Name <- "William"
wk.NameChanged.Add(fun () -> printfn "-- Another handler attached to NameChanged!")
wk.Name <- "Bill"

wk.ShiftChanged.Add(fun () -> printfn "Worker changed shift! New shift: %s" wk.Shift)
wk.Shift <- "Morning"
wk.ShiftChanged.Add(fun () -> printfn "-- Another handler attached to ShiftChanged!")
wk.Shift <- "Night"

Когда вы компилируете и запускаете программу, она выдает следующий вывод: