2013-06-03 8 views
15

Ich habe einen Akteur, der beim Empfang einer Nachricht das Dateisystem nach einer Datei durchsucht und den vollständigen Pfad der Datei zurückgibt.Absender in einer Zukunft

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") 
    } 

} 

Aber ich habe festgestellt, dass es die Nachricht an akka://FileSystem/deadLetters und nicht die sender zurück:

es asynchron zu halten, habe ich getan. Dokumentation sagt das:

Nur gültig innerhalb des Schauspielers selbst, also schließen Sie nicht darüber und * veröffentlichen Sie es zu anderen Themen!

Also heißt es, ich muss es unbedingt synchron halten? Gibt es einen anderen Weg?

+0

Warum eine Zukunft nutzen? Es ist eine E/A-Operation (und so möglicherweise blockiert), also setzen Sie den Actor auf die Blockierung-IO-Dispatcher. Wenn Sie mehrere Dateien gleichzeitig suchen müssen, führen Sie mehrere Instanzen aus. –

Antwort

32

Sie sind einen sehr häufigen Fehler von „closing über veränderbaren Zustand“ zu machen. Die Schließung, die Sie an onComplete übergeben, macht keine Kopie von this.sender, also wenn Ihre onComplete aufgerufen wird, senden Sie die Nachricht an was auch immer this.sender zeigt auf, zu dem Zeitpunkt, zu dem es zeigte, wenn Sie die Schließung erstellt.

Sie können dieses Problem vermeiden, indem Sie Ihre eigene lokale, unveränderliche Kopie des aktuellen Inhalts von this.sender und Referenz Schaffung dieses Wert in der Schließung:

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

ist das auch für 'self' notwendig? –

+1

@GeorgePligor Nein, das Selbst ist nicht veränderbar. – stew

4
import akka.pattern.pipe 

Macht den Trick. Doing:

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

Antworten zurück an den Absender

+8

Es scheint, als ob diese Antwort falsch oder irreführend auf PipeTo konzentriert ist. Soweit ich weiß, mit PipeTo statt! hat das Problem nicht behoben. Das Speichern des Absenders in "reply" verhindert das Verhalten, das Sie zuvor gesehen haben. Darauf konzentriert sich die Antwort von stew. – mushroom