【问题标题】:sender inside a future未来中的发件人
【发布时间】:2013-05-29 16:27:56
【问题描述】:

我有一个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 内部有效,因此不要关闭它并 * 发布到其他线程!

这是否意味着,我必须保持同步?还有其他方法吗?

【问题讨论】:

  • 为什么要使用未来?这是一个 I/O 操作(因此可能是阻塞的),所以将参与者放在阻塞 io 调度程序上。如果您需要一次搜索多个文件,请运行多个实例。

标签: scala akka


【解决方案1】:
import akka.pattern.pipe

成功了。正在做:

val reply = sender
future {
  val ans = searchAndCache(s)
  println("Input Request: "+s+" output:"+ans+" "+reply.path)
  ans
} pipeTo reply

回复发件人

【讨论】:

  • 这个答案似乎错误地或误导地集中在 pipeTo 上。据我所知,使用 pipeTo 而不是 !没有解决问题。将发件人保存在“回复”中可以防止您之前看到的行为,这是炖菜的答案所关注的。
【解决方案2】:

您犯了一个非常常见的错误,即“关闭可变状态”。您传递给onComplete 的闭包不会复制this.sender,因此当您的onComplete 被调用时,您会将消息发送到当时this.sender 碰巧指向的对象,而不是它指向的对象当你创建闭包时。

您可以通过为this.sender 的当前内容创建自己的本地不可变副本并在闭包中引用该值来避免此问题:

val origSender = sender
f.onComplete {
    case Successs(x) => origSender ! x
    ...
}

【讨论】:

  • self 也需要这样做吗?
  • @GeorgePligor 不,self 不可变。
【解决方案3】:

我知道这是旧的,但我必须添加这个,
pipeTo 是正确的方式,但您不需要复制您的发件人
您已经处于相同的环境中。
实际上 pipeTo 会为您执行此操作。
它将采用当前的发件人参考(通过传递给它的参数)
并用它来为你解决未来(看看它的实现)
就这样吧:

future {
  val ans = searchAndCache(s)
  println("Input Request: "+s+" output:"+ans+" "+reply.path)
  ans
} pipeTo reply

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-29
    • 1970-01-01
    • 2012-12-28
    • 2012-04-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多