共用方式為


Control.Observable 模組 (F#)

更新:2010 年 10 月

第一級事件和其他可預見物件上的基本作業。

命名空間/模組路徑: Microsoft.FSharp.Control

組件:FSharp.Core (在 FSharp.Core.dll 中)

module Observable

說明

add : ('T -> unit) -> IObservable<'T> -> unit

建立觀察器,這個觀察器會永久訂閱指定的可預見值,以及呼叫每個觀測之指定的函式。

choose : ('T -> 'U option) -> IObservable<'T> -> IObservable<'U>

傳回可預見值,這個可預見值會使用指定的函式從來源中選擇觀測投影。 傳回的物件會觸發觀察值的分隔器傳回一個 Some值。 傳回的物件也會傳播從來源引發的所有錯誤,並且於來源完成時完成。

filter : ('T -> bool) -> IObservable<'T> -> IObservable<'T>

傳回可預見值,這個可預見值會透過指定的函式來篩選來源的觀測。 observable 會看到的述詞傳回 這些觀察 true 每一個已訂閱之觀察器的述詞都會執行一次。 傳回的物件也會傳播自來源引發的錯誤觀測,並且於來源完成時完成。

map : ('T -> 'U) -> IObservable<'T> -> IObservable<'U>

傳回可預見值,這個可預見值會透過指定的函式來轉換來源的觀測。 每個已訂閱的觀察器都會執行轉換函式一次。 傳回的物件也會傳播自來源引發的錯誤觀測,並且於來源完成時完成。

merge : IObservable<'T> -> IObservable<'T> -> IObservable<'T>

對來源中的合併觀測傳回可預見值。 傳回的物件會傳播從任一來源引發的成功和錯誤值,並於兩個來源皆已完成時完成。

pairwise : IObservable<'T> -> IObservable<'T * 'T>

傳回新的可預見值,這個可預見值會在輸入可預見值的第二個和後續觸發動作時觸發。 輸入可預見值的第 N 個觸發動作,會從成對的第 N-1 個和第 N 個觸發動作來傳遞引數。 傳遞給第 N-1 個觸發動作的引數會保留在隱藏的內部狀態中,直到第 N 個觸發動作發生為止。

partition : ('T -> bool) -> IObservable<'T> -> IObservable<'T> * IObservable<'T>

傳回兩個可預見值,這兩個可預見值會透過指定的函式來分割來源的觀測。 第一個會觸發的述詞傳回 這些值的觀察值 true 第二個會觸發位置述詞傳回 這些值的觀察值 false 每一個已訂閱之觀察器的述詞都會執行一次。 兩者也會傳播自來源引發的錯誤觀測,而且來源完成時這兩者也都完成。

scan : ('U -> 'T -> 'U) -> 'U -> IObservable<'T> -> IObservable<'T>

傳回可預見值,針對每一個觀察器,配置狀態項目並將指定的累積函式套用到從輸入引發的後續值。 傳回的物件將會針對每一個計算的狀態值 (不包含初始值) 觸發觀測。 傳回的物件會傳播從來源引發的所有錯誤,並且於來源完成時完成。

split : ('T -> Choice<'U1,'U2>) -> IObservable<'T> -> IObservable<'U1> * IObservable<'U2>

傳回兩個可預見值,這兩個可預見值會透過指定的函式來分割來源的觀測。 第一個會觸發觀察值的分隔器傳回 Choice1Of2 第二個會觸發觀察值 y的分隔器已傳回 Choice2Of2 針對每個訂閱的觀察者,分隔器被執行一次。 兩者也會傳播自來源引發的錯誤觀測,而且來源完成時這兩者也都完成。

訂閱 : ('T -> unit) -> IObservable<'T> -> IDisposable

建立觀察器,這個觀察器會訂閱指定的可預見值,以及呼叫每個觀測之指定的函式。

範例

下列程式碼範例會示範如何使用 observables。 ObserverSource在這個範例中定義的類別是一般用途的可重複使用類別,您可以用它做為來源的 顯著的事件。 在這個模組中使用某些功能的範例如下所示,您可以不在這裡示範的函式請參閱程式碼範例在 Control.Event 模組 (F#)

open System
open System.Diagnostics

// Represents a stream of IObserver events.
type ObservableSource<'T>() =

    let protect function1 =
        let mutable ok = false
        try 
            function1()
            ok <- true
        finally
            Debug.Assert(ok, "IObserver method threw an exception.")

    let mutable key = 0

    // Use a Map, not a Dictionary, because callers might unsubscribe in the OnNext
    // method, so thread-safe snapshots of subscribers to iterate over are needed.
    let mutable subscriptions = Map.empty : Map<int, IObserver<'T>>

    let next(obs) = 
        subscriptions |> Seq.iter (fun (KeyValue(_, value)) -> 
            protect (fun () -> value.OnNext(obs)))

    let completed() = 
        subscriptions |> Seq.iter (fun (KeyValue(_, value)) -> 
            protect (fun () -> value.OnCompleted()))

    let error(err) = 
        subscriptions |> Seq.iter (fun (KeyValue(_, value)) -> 
            protect (fun () -> value.OnError(err)))

    let thisLock = new obj()

    let obs = 
        { new IObservable<'T> with
            member this.Subscribe(obs) =
                let key1 =
                    lock thisLock (fun () ->
                        let key1 = key
                        key <- key + 1
                        subscriptions <- subscriptions.Add(key1, obs)
                        key1)
                { new IDisposable with 
                    member this.Dispose() = 
                        lock thisLock (fun () -> 
                            subscriptions <- subscriptions.Remove(key1)) } }

    let mutable finished = false

    // The source ought to call these methods in serialized fashion (from
    // any thread, but serialized and non-reentrant).
    member this.Next(obs) =
        Debug.Assert(not finished, "IObserver is already finished")
        next obs

    member this.Completed() =
        Debug.Assert(not finished, "IObserver is already finished")
        finished <- true
        completed()

    member this.Error(err) =
        Debug.Assert(not finished, "IObserver is already finished")
        finished <- true
        error err

    // The IObservable object returned is thread-safe; you can subscribe 
    // and unsubscribe (Dispose) concurrently.
    member this.AsObservable = obs

// Create a source.
let source = new ObservableSource<int>()

// Get an IObservable from the source.
let obs = source.AsObservable 

// Add a simple subscriber.
let unsubA = obs |> Observable.subscribe (fun x -> printfn "A: %d" x)

// Send some messages from the source.
// Output: A: 1
source.Next(1)
// Output: A: 2
source.Next(2)

// Add another subscriber. This subscriber has a filter.
let unsubB =
    obs
    |> Observable.filter (fun num -> num % 2 = 0)
    |> Observable.subscribe (fun num -> printfn "B: %d" num)

// Send more messages from the source.
// Output: A: 3
source.Next(3)
// Output: A: 4
//         B: 4
source.Next(4)

// Have subscriber A unsubscribe.
unsubA.Dispose()

// Send more messages from the source.
// No output
source.Next(5)
// Output: B: 6
source.Next(6)

// If you use add, there is no way to unsubscribe from the event.
obs |> Observable.add(fun x -> printfn "C: %d" x)

// Now add a subscriber that only does positive numbers and transforms
// the numbers into another type, here a string.
let unsubD =
    obs |> Observable.choose (fun int1 ->
             if int1 >= 0 then None else Some(int1.ToString()))
        |> Observable.subscribe(fun string1 -> printfn "D: %s" string1)

let unsubE =
    obs |> Observable.filter (fun int1 -> int1 >= 0)
        |> Observable.subscribe(fun int1 -> printfn "E: %d" int1)

let unsubF =
    obs |> Observable.map (fun int1 -> int1.ToString())
        |> Observable.subscribe (fun string1 -> printfn "F: %s" string1)


平台

Windows 7、Windows Vista SP2、Windows XP SP3、Windows XP x64 SP2、Windows Server 2008 R2、Windows Server 2008 SP2、Windows Server 2003 SP2

版本資訊

F# 執行階段

支援版本:2.0、4.0

Silverlight

支援版本:3

請參閱

參考

Microsoft.FSharp.Control 命名空間 (F#)

變更記錄

日期

History

原因

2010 年 10 月

加入程式碼範例。

資訊加強。