4

アクターモデルでは、アクターには、たとえばパターンマッチング(言語ofcに応じて)を使用してメッセージがマッチングされる、ある種のメッセージループがあります。

例:疑似F#

 let message_loop() = 
     let! message = receive_message() //sync receive message
     match message with
     | Foo(a,b) -> DoStuff(a,b)
     | Bar(c) -> DoOtherStuff(c)
     | _ -> error ("unknown message")
     message_loop()

ほとんどの場合、メッセージ署名は一致し、メッセージコンテンツに対して実行するアクションに関連付けられます。

これと実際のメソッドの呼び出しの間に概念的な違いはありますか?たとえば、C#5で次のことを行う場合:

class MyActor 
{
   //message signature Foo(a,b)
   public void Foo(int a,string b)
   {
      Act( () => DoStuff(a,b) );
   }

   //message signature Bar(c)
   public void Bar(int c)
   {
      Act( () => DoOtherStuff(c));
   }

   // the rest is infrasturcture code, can be refactored into an Actor Base class


   //this emulates the sync behavior of the above actor
   //each action is pushed onto a queue 
   //and then processed synchronously by the message handler
   private void Act(Action action)
   {
       actions.Post(action); 
   }

   private BufferBlock<Action> actions = new BufferBlock<Action>();

   //this needs max degreee of parallellism = 1 
   private ActionBlock<Action> messageHandler = new ....
}

このように、MyActorでメソッドを呼び出すと、単一の種類のメッセージのみを処理する非同期メッセージがメッセージキューに投稿されます。行動。ただし、メッセージに関連付けられている動作は、メッセージ自体に含まれています(パブリックメソッドから投稿されます)

それで、これはC#5 / Async CTPでアクターを実行するためのクリーンな方法と見なされますか?

利点は、メッセージがクラスのような厄介なメッセージDTOを作成するのではなく、通常のメッセージとして単純に定義されることです。

それで、これはそれを機能させるのに十分でしょうか?

4

2 に答える 2

1

タスクベースの非同期と MailboxProcessor にはわずかな違いがあります。メールボックス プロセッサは、Winforms メッセージ ループと同様に、常に同じスレッドで終了します。タスクは SynchronizationContext を保持します。これは、Winforms と WPF で同じ動作をすることを意味しますが、スレッド プールを操作するときに別のスレッドになる可能性があります。

そうでなければ、そして概念的には、私には正しいように見えます。

于 2011-05-17T13:15:12.607 に答える
0

あなたのアプローチは合理的だと思います。

実際には、F# エージェントをインターフェイスの背後にカプセル化し、それ自体がメッセージをエージェントにディスパッチすることをお勧めします。

type IPrintText =
    abstract Stop : unit -> unit
    abstract Print : string -> unit

module Printer =
    type private Message =
        | PrintText of string
        | Stop

    let Start () =
        let agent =
            MailboxProcessor.Start (fun inbox ->
                    let rec loop () = async {
                            let! msg = inbox.Receive()

                            return!
                                match msg with
                                | PrintText text ->
                                    printfn "%s" text
                                    loop ()
                                | Stop -> async.Zero()
                        }
                    loop ())

        { new IPrintText with
            member x.Stop () = agent.Post Stop
            member x.Print text = agent.Post <| PrintText text }

let agent = Printer.Start ()

agent.Print "Test"
agent.Stop ()
于 2011-11-18T16:02:45.680 に答える