スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

F#入門中級編第22回(Asynchronous Workflows(8) MailboxProcessor(3))

今回は前回作成したメッセージキューに整数を入れると、それらの和と、偶数だけの和を保持しながら働くというagentをクラス化してみたいと思います。
 
まずは前回のコードを再掲します。
 
type msg = 
    |Work of int
    |Stop
    |FetchAllSum of AsyncReplyChannel<int>
    |FetchEvenSum of AsyncReplyChannel<int>
 
let fetchable2wayAgent00 = MailboxProcessor.Start(fun inbox ->
                        let rec loop (allSum,evenSum) =
                            async{let! msg = inbox.Receive()
                                  match msg with
                                  | Work(i) ->
                                        let newAllSum = allSum + i 
                                        let newEvenSum =
                                            if i % 2 = 0 then
                                                evenSum + i
                                            else
                                                evenSum
                                        
                                        return! loop (newAllSum,newEvenSum) 
                                  | Stop ->
                                        return ()
                                  | FetchAllSum(replyChannel) -> 
                                        replyChannel.Reply(allSum) 
                                        return! loop (allSum,evenSum)
                                  | FetchEvenSum(replyChannel) ->
                                        replyChannel.Reply(evenSum)
                                        return! loop (allSum,evenSum)
                            }
                        loop (0,0))
                        
さて、それではこれをクラス化してみます。
 
>type msg = 
    |Work of int
    |Stop
    |FetchAllSum of AsyncReplyChannel<int>
    |FetchEvenSum of AsyncReplyChannel<int>
 
type fetchable2WayAgent() =
        let innerAgent =
                  MailboxProcessor.Start(fun inbox ->
                        let rec loop (allSum,evenSum) =
                            async{let! msg = inbox.Receive()
                                  match msg with
                                  | Work(i) ->
                                        let newAllSum = allSum + i 
                                        let newEvenSum =
                                            if i % 2 = 0 then
                                                evenSum + i
                                            else
                                                evenSum
                                        
                                        return! loop (newAllSum,newEvenSum) 
                                  | Stop ->
                                    return ()
                                  | FetchAllSum(replyChannel) -> 
                                        replyChannel.Reply(allSum) 
                                        return! loop (allSum,evenSum)
                                  | FetchEvenSum(replyChannel) ->
                                        replyChannel.Reply(evenSum)
                                        return! loop (allSum,evenSum)
                            }
                        loop (0,0))
        member this.PostInt(i) = innerAgent.Post(Work(i))
        member this.FetchAllSum() = innerAgent.PostAndReply(fun replyChannel -> FetchAllSum(replyChannel))
        member this.FetchEvenSum() = innerAgent.PostAndReply(fun replyChannel -> FetchEvenSum(replyChannel))
        member this.Stop() = innerAgent.Post(Stop);;
        
type msg =
  | Work of int
  | Stop
  | FetchAllSum of AsyncReplyChannel<int>
  | FetchEvenSum of AsyncReplyChannel<int>
type fetchable2WayAgent =
  class
    new : unit -> fetchable2WayAgent
    member FetchAllSum : unit -> int
    member FetchEvenSum : unit -> int
    member PostInt : i:int -> unit
    member Stop : unit -> unit
  end
    
では使ってみます。
 
> let agent0 = new fetchable2WayAgent();;
val agent0 : fetchable2WayAgent
 
> agent0.PostInt(1);;
val it : unit = ()
 
> agent0.PostInt(2);;
val it : unit = ()
 
> agent0.FetchAllSum();;
val it : int = 3
 
> agent0.FetchEvenSum();;
val it : int = 2
 
> agent0.Stop();;
val it : unit = ()

 
上の例ではnewでインスタンスを生成した時点で、非同期処理が開始されますが、別のタイミングで開始したい場合は、例えば次のようにします。(変更点は2行だけです。)
 
type msg = 
    |Work of int
    |Stop
    |FetchAllSum of AsyncReplyChannel<int>
    |FetchEvenSum of AsyncReplyChannel<int>
 
type fetchable2WayAgent2() =
        let innerAgent =
                  new MailboxProcessor<msg>(fun inbox -> //#この行を変更
                        let rec loop (allSum,evenSum) =
                            async{let! msg = inbox.Receive()
                                  match msg with
                                  | Work(i) ->
                                        let newAllSum = allSum + i 
                                        let newEvenSum =
                                            if i % 2 = 0 then
                                                evenSum + i
                                            else
                                                evenSum
                                        
                                        return! loop (newAllSum,newEvenSum) 
                                  | Stop ->
                                    return ()
                                  | FetchAllSum(replyChannel) -> 
                                        replyChannel.Reply(allSum) 
                                        return! loop (allSum,evenSum)
                                  | FetchEvenSum(replyChannel) ->
                                        replyChannel.Reply(evenSum)
                                        return! loop (allSum,evenSum)
                            }
                        loop (0,0))
        member this.Start() = innerAgent.Start() //#この行追加
        member this.PostInt(i) = innerAgent.Post(Work(i))
        member this.FetchAllSum() = innerAgent.PostAndReply(fun replyChannel -> FetchAllSum(replyChannel))
        member this.FetchEvenSum() = innerAgent.PostAndReply(fun replyChannel -> FetchEvenSum(replyChannel))
        member this.Stop() = innerAgent.Post(Stop)
 
使用例
 
> let agent2 = new fetchable2WayAgent2();;
val agent2 : fetchable2WayAgent2
 
> agent2.Start();;
val it : unit = ()
 
> agent2.PostInt(1);;
val it : unit = ()
 
> agent2.FetchEvenSum();;
val it : int = 0
 
> agent2.Stop();;
val it : unit = ()
スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

コメントの投稿

非公開コメント

プロフィール

T GYOUTEN

Author:T GYOUTEN
F#と英単語とフリーソフトと読書に興味があります。
ホームページでフリーソフトも公開しています。どぞ御贔屓に。

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
フリーエリア
フリーエリア
blogram投票ボタン
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。