Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在F#Akka.NET Actor中存储状态?_F#_Actor_Akka.net - Fatal编程技术网

如何在F#Akka.NET Actor中存储状态?

如何在F#Akka.NET Actor中存储状态?,f#,actor,akka.net,F#,Actor,Akka.net,在C#ReceiveActors中,我可以将state作为类中的私有字段。我应该如何使用F#API以惯用的方式实现这一点 这是个好主意吗?还有别的选择吗 let handleMessage (mailbox: Actor<'a>) msg = let mutable i = 1 match msg with | Some x -> i <- i + x | None -> () let handleMessage(mailbox:A

在C#
ReceiveActor
s中,我可以将state作为类中的私有字段。我应该如何使用F#API以惯用的方式实现这一点

这是个好主意吗?还有别的选择吗

let handleMessage (mailbox: Actor<'a>) msg =
    let mutable i = 1
    match msg with
    | Some x -> i <- i + x
    | None -> ()

let handleMessage(mailbox:Actor您提出的方法完全适合作为在Actor中存储状态的一种方法。任何时候只处理1条消息的并发约束意味着不可能由于共享内存位置上的争用而进入无效状态

然而,这并不是最惯用的选项。Akka.Net提供了一个F#API,以类似于F#MailboxProcessors的方式与参与者一起工作。在本例中,您将参与者定义为一个尾部递归函数,它使用一些新状态调用自身。下面是一个示例

spawn system "hello" <|
    fun mailbox ->
        let rec loop state =
            actor {
                let! msg = mailbox.Receive ()
                printfn "Received %A. Now received %s messages" msg state
                return! loop (state + 1) //Increment a counter for the number of times the actor has received a message
            }
        loop 0
spawn系统“你好”
让rec循环状态=
演员{
let!msg=mailbox.Receive()
printfn“已收到%A.现在已收到%s消息”消息状态
return!loop(state+1)//根据参与者接收消息的次数递增计数器
}
循环0

有关Akka.Net F#API的完整文档,请参见

有两种解决方案,它们都使用明确的递归循环定义,这是Akka F#actors的主要概念

首先,您可以在循环定义之前定义变量,该变量应该仅在参与者的作用域内可见(在下面的示例中,我将
I
定义更改为引用单元格,因为闭包无法捕获可变变量):

让actorRef=
繁殖系统“我的演员”
设i=ref 1
让rec循环()=
演员{
let!msg=mailbox.Receive()
配味精
|一些x->i:=!i+x
|无->()
return!loop()
}
循环()
然而,更明智的解决方案是在消息处理期间保持状态不变,并且仅在传入下一个循环调用时更改状态,如下所示:

let actorRef = 
    spawn system "my-actor" <| fun mailbox -> 
        let rec loop i = 
            actor { 
                let! msg = mailbox.Receive()
                match msg with
                | Some x -> return! loop (i + x)
                | None -> return! loop i
            }
        loop 1  // invoke first call with initial state
让actorRef=
繁殖系统“我的演员”
让rec循环i=
演员{
let!msg=mailbox.Receive()
配味精
|某些x->返回!循环(i+x)
|无->返回!循环i
}
循环1//使用初始状态调用第一个调用

不是你想要的,而是你想要的。然而,如果Akka.NET强迫你走上面向突变的道路,那么它可能不可能“很好地”完成。除了从
ReceiveActor派生之外,你能用其他方式为Akka.NET实现一个actor吗?
?这可以让你使用递归轮询循环吗?顺便说一句,如果有另一个惯用的解决方案的话蒂昂,我只是不知道,我也想接受教育:)
let actorRef = 
    spawn system "my-actor" <| fun mailbox -> 
        let rec loop i = 
            actor { 
                let! msg = mailbox.Receive()
                match msg with
                | Some x -> return! loop (i + x)
                | None -> return! loop i
            }
        loop 1  // invoke first call with initial state