Scala 未来的寄件人

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

我有一个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
而不是
发送者
。文件说:

仅在参与者本身内有效,因此不要关闭它并 *发布到其他线程

这是否意味着,我必须保持同步?还有别的办法吗

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调度程序上。如果需要同时搜索多个文件,请运行多个实例。