Scala 未来的寄件人
我有一个actor,它在收到消息时在文件系统中搜索一个文件并返回文件的完整路径 为了保持异步,我做了以下工作:Scala 未来的寄件人,scala,akka,Scala,Akka,我有一个actor,它在收到消息时在文件系统中搜索一个文件并返回文件的完整路径 为了保持异步,我做了以下工作: def receive = { case s:String => { val f = future{ val ans = search(s) println("Input Request: "+s+" output:"+ans+" "+sender.path) } f.onComplete{ case Succes
def receive = {
case s:String => {
val f = future{
val ans = search(s)
println("Input Request: "+s+" output:"+ans+" "+sender.path)
}
f.onComplete{
case Success(x) => sender ! x
case Failure(y) => println("Could not complete it")
}
}
}
但我注意到它将消息返回到akka://FileSystem/deadLetters
而不是发送者
。文件说:
仅在参与者本身内有效,因此不要关闭它并
*发布到其他线程
这是否意味着,我必须保持同步?还有别的办法吗
import akka.pattern.pipe
这就是诀窍。做:
val reply = sender
future {
val ans = searchAndCache(s)
println("Input Request: "+s+" output:"+ans+" "+reply.path)
ans
} pipeTo reply
回复发件人您犯了一个非常常见的错误,即“关闭可变状态”。传递给
onComplete
的闭包不会复制this.sender
,因此当调用onComplete
时,您会将消息发送给this.sender
当时指向的对象,而不是创建闭包时指向的对象
您可以通过创建自己的本地、不可变的this.sender
当前内容副本,并在闭包中引用该值来避免此问题:
val origSender = sender
f.onComplete {
case Successs(x) => origSender ! x
...
}
我知道这很旧,但我必须补充一点,
pipeTo是正确的方法,但是您不需要复制您的发件人,
您已经处于相同的上下文中。
实际上,pipeTo是为您做这件事的。
它将采用当前发送方引用(通过传递给它的参数)
并用它来为您解决未来(看看它的实现)
只要做:
future {
val ans = searchAndCache(s)
println("Input Request: "+s+" output:"+ans+" "+reply.path)
ans
} pipeTo reply
这个答案似乎错误地或误导性地集中在pipeTo上。据我所知,使用pipeTo而不是!没有解决问题。在“回复”中保存发件人可以防止您以前看到的行为,这也是斯图的回答重点。这对
self
也是必要的吗?@geogepligor不,self是不可变的。为什么要使用未来?这是一个I/O操作(因此可能是阻塞),因此将参与者放在阻塞io调度程序上。如果需要同时搜索多个文件,请运行多个实例。