我有一个接收消息的actor,在文件系统中搜索文件并返回文件的完整路径。
为了保持异步,我做了:
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
而不是sender
。文档说:
仅在Actor本身内有效,所以不要关闭它 *将其发布到其他线程!
这是否意味着,我必须保持同步?还有其他方法吗?
答案 0 :(得分:44)
你正在犯一个“关闭可变状态”的错误。您传递给onComplete
的关闭不会复制this.sender
,因此当您onComplete
被调用时,您正在将消息发送到指向的this.sender
{}}那个时候,而不是你创建闭包时指出的那个。
您可以通过创建自己的this.sender
当前内容的本地不可变副本来避免此问题,并在闭包中引用该值:
val origSender = sender
f.onComplete {
case Successs(x) => origSender ! x
...
}
答案 1 :(得分:4)
import akka.pattern.pipe
诀窍。这样做的:
val reply = sender
future {
val ans = searchAndCache(s)
println("Input Request: "+s+" output:"+ans+" "+reply.path)
ans
} pipeTo reply
回复发件人
答案 2 :(得分:0)
我知道这已经过时了,但我必须补充一点,
pipeTo 是正确的方法,但您无需复制发件人,
你已经在同一个环境中了
实际上管道是为你做的。
它将采用当前发送者引用(通过传递给它的参数)
并用它来为你解决未来(看看它的实施)
只是做:
future {
val ans = searchAndCache(s)
println("Input Request: "+s+" output:"+ans+" "+reply.path)
ans
} pipeTo reply