F # - События
События позволяют классам отправлять и получать сообщения между собой.
В графическом интерфейсе событиями являются действия пользователя, такие как нажатие клавиш, щелчки, движения мыши и т. Д., Или некоторые события, такие как уведомления, созданные системой. Приложениям необходимо реагировать на события, когда они происходят. Например, прерывания. События используются для межпроцессного взаимодействия.
Объекты общаются друг с другом посредством синхронной передачи сообщений.
События привязаны к другим функциям; реестр объектовcallback функции для события, и эти обратные вызовы выполняются, когда (и если) событие запускается каким-либо объектом.
Класс событий и модуль событий
Класс Control.Event <'T> помогает в создании наблюдаемого объекта или события.
У него есть следующие члены экземпляра для работы с событиями:
Член | Описание |
---|---|
Публиковать | Публикует наблюдение как первоклассную ценность. |
Спусковой крючок | Запускает наблюдение с использованием заданных параметров. |
Модуль Control.Event предоставляет функции для управления потоками событий -
Значение | Описание |
---|---|
добавить: ('T → unit) → Event <' Del, 'T> → unit | Запускает заданную функцию каждый раз, когда запускается данное событие. |
выберите: ('T →' U option) → 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> | Возвращает новое событие, которое запускается при втором и последующих запусках входного события. ВNth запуск входного события передает аргументы из N-1th и Nthзапускается как пара. Аргумент, переданный вN-1th запуск сохраняется в скрытом внутреннем состоянии до Nth происходит срабатывание. |
раздел: ('T → bool) → IEvent <' Del, 'T> → IEvent <' T> * IEvent <'T> | Возвращает новое событие, которое прослушивает исходное событие и запускает первое результирующее событие, если применение предиката к аргументам события вернуло истину, и второе событие, если оно вернуло ложь. |
сканирование: ('U →' T → 'U) →' U → IEvent <'Del,' T> → IEvent <'U> | Возвращает новое событие, состоящее из результатов применения данной функции накопления к последовательным значениям, инициированным для входного события. Элемент внутреннего состояния записывает текущее значение параметра состояния. Внутреннее состояние не заблокировано во время выполнения функции накопления, поэтому следует позаботиться о том, чтобы входной IEvent не запускался одновременно несколькими потоками. |
split: ('T → Выбор <' U1, 'U2>) → IEvent <' Del, 'T> → IEvent <' U1> * IEvent <'U2> | Возвращает новое событие, которое прослушивает исходное событие и запускает первое результирующее событие, если приложение функции к аргументам события вернуло Choice1Of2, и второе событие, если оно возвращает Choice2Of2. |
Создание событий
События создаются и используются через 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 Add: event :( 'T → unit) → unit | Подключает функцию прослушивателя к событию. Слушатель будет вызываться при срабатывании события. |
val AddHandler: 'del → unit | Подключает объект делегата обработчика к событию. Позднее обработчик можно удалить с помощью RemoveHandler. Слушатель будет вызываться при срабатывании события. |
val RemoveHandler: 'del → unit | Удаляет делегата слушателя из хранилища слушателей событий. |
В следующем разделе представлен полный пример.
пример
Следующий пример демонстрирует концепцию и методы, обсужденные выше.
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"
Когда вы компилируете и выполняете программу, она дает следующий результат:
Worker changed name! New name: William
Worker changed name! New name: Bill
-- Another handler attached to NameChanged!
Worker changed shift! New shift: Morning
Worker changed shift! New shift: Night
-- Another handler attached to ShiftChanged!