3

私はF#がテーブルにもたらすすべての機能をゆっくりと調べてきました。私の興味を特に惹きつけたのはMailboxProcessorです。

  1. C#でこれに相当するものは、おそらくロックを使用します。MailboxProcessorロックの代わりと見なすことができますか?
  2. 次の例では、私は特に素朴なことをしていますか、それとも改善される可能性のある何かを見ることができますか?


module Tcp =
    open System
    open System.Collections.Generic
    open System.Net
    open System.Net.Sockets
    open System.Threading    

    type SocketAsyncMessage =
        | Get of AsyncReplyChannel<SocketAsyncEventArgs>
        | Put of SocketAsyncEventArgs
        | Dispose of AsyncReplyChannel<MailboxProcessor<SocketAsyncMessage>>

    type SocketAsyncEventArgsPool(size:int) =             
        let agent = 
            lazy(MailboxProcessor.Start(
                    (fun inbox ->
                        let references = lazy(new List<SocketAsyncEventArgs>(size))       
                        let idleReferences = lazy(new Queue<SocketAsyncEventArgs>(size))                    
                        let rec loop () = 
                            async {
                                let! message = inbox.Receive()
                                match message with
                                | Get channel -> 
                                    if idleReferences.Value.Count > 0 then
                                        channel.Reply(idleReferences.Value.Dequeue())
                                    else    
                                        let args = new SocketAsyncEventArgs()
                                        references.Value.Add args
                                        channel.Reply args  
                                    return! loop()
                                | Put args ->
                                    if args = null then
                                        nullArg "args" 
                                    elif references.Value.Count < size then
                                        idleReferences.Value.Enqueue args
                                    else                                       
                                        if not(references.Value.Remove args) then
                                            invalidOp "Reference not found."                                        
                                        args.Dispose() 
                                    return! loop()
                                | Dispose channel ->
                                    if references.IsValueCreated then
                                        references.Value 
                                        |> Seq.iter(fun args -> args.Dispose())
                                    channel.Reply inbox 
                            }
                        loop())))

        /// Returns a SocketAsyncEventArgs instance from the pool.         
        member this.Get () =
            agent.Value.PostAndReply(fun channel -> Get channel)            
        /// Returns the SocketAsyncEventArgs instance to the pool. 
        member this.Put args =
            agent.Value.Post(Put args)
        /// Releases all resources used by the SocketAsyncEventArgsPool.
        member this.Dispose () =
            (this:>IDisposable).Dispose()  

        interface IDisposable with
             member this.Dispose() =
                if agent.IsValueCreated then
                    (agent.Value.PostAndReply(fun channel -> Dispose channel):>IDisposable).Dispose()
4

2 に答える 2

6

メールボックス(および同様の構造)は、本質的に非同期処理を中心に構築されているため、ロックを使用しないプログラミングモデルで使用されます。(共有された可変状態の欠如は、このモデルのもう1つの要件です)。

アクターモデルは、相互にデータを送受信することによって通信する一連のシングルスレッドミニアプリケーションと考えることができます。各ミニアプリケーションは、一度に1つのスレッドによってのみ実行されます。これは、共有状態の欠如と相まって、ロックを不要にします。

手続き型モデル(およびほとんどのオブジェクト指向コードは、本質的に手続き型です)は、スレッドレベルの同時実行性、および他のオブジェクトへの同期呼び出しを使用します。アクターモデルはこれを反転させます-オブジェクト間の呼び出し(メッセージ)は非同期ですが、各オブジェクトは完全に同期しています。

率直に言って、コードを実際に分析するのに十分なF#がわかりません。同期しているように見えるシェルをメールボックスの周りに貼り付けようとしているように見えますが、それが本当に最善の方法であるかどうか疑問に思います(メールボックスモデルを完全に採用するのではなく)。実装では、ロックの代わりに使用しているように見えます。

于 2010-02-08T06:19:08.080 に答える
0

あなたの質問の最初の部分へ:

MailboxProcessorクラスは、独自のスレッドで実行されるメッセージキューです。非同期または同期のように、任意のスレッドからMailboxProcessorにメッセージを送信できます。

このようなモデルでは、locks / mutexes / ipcメカニズムを使用する代わりに、メッセージパッシングを介してスレッド間で通信できます。

于 2010-02-08T06:31:49.490 に答える