2015-07-10 6 views
5

Hier the official sample von PipeTo() in Akka.NET mit:Warum sollte ich den Sender mit PipeTo() schließen?

Receive<BeginProcessFeed>(feed => 
{ 
    //instance variable for closure 
    var senderClosure = Sender; 
    SendMessage(string.Format("Downloading {0} for RSS/ATOM processing...", feed.FeedUri)); 

    //reply back to the sender 
    _feedFactory.CreateFeedAsync(feed.FeedUri).PipeTo(senderClosure); 
}); 

Die Frage ist, warum sollten wir hier Sender Schließung benutzen? Warum nicht einfach zu verwenden:

_feedFactory.CreateFeedAsync(feed.FeedUri).PipeTo(Sender); 

In diesem Beispiel und in dem docs es gesagt ist es zwingend notwendig, Schließung hier zu verwenden. Aber ich sehe keine Gründe dafür.

Wenn wir ContinueWith() verwendet haben, ist es sinnvoll, den Abschluss in der Fortsetzung zu verwenden, aber nicht als PipeTo() Parameter.

Vermisse ich etwas?

Antwort

5

Zwei Dinge hier zu verstehen:

  1. Sender keine statische Eigenschaft ist. Sender is actually a function on the IActorContext, die den Absender der aktuellen Nachricht zurückgibt, die verarbeitet wird. Der zurückgegebene Wert ändert sich jedes Mal, wenn der Kontext eine neue Nachricht vom Postfach erhält.

  2. PipeTo ist eine Fortsetzung, und wenn diese Fortsetzung auf dem Threadpool ausgeführt wird, wird Zugriff auf genau die gleiche IActorContext Objekt Sender Aufruf, der die Aufgabe gestartet. Es gibt keine Garantie, dass der aktuelle Sender im Kontext derselbe ist, weil neue Nachrichten in den Aktor zur Verarbeitung seit dem Start der Aufgabe geschoben werden.

So cachen wir den Wert von Sender in einer lokalen Variablen zu garantieren, dass wir PipeTo an den richtigen IActorRef, wenn es ausführt, sind mit dem Ziel.

+1

Das von Ihnen beschriebene Problem tritt auf, wenn der Compiler "this" im Kontext einer Schließung erfasst. Zum Beispiel passiert es, wenn wir "this" -Members (wie Sender) in Lambda-Ausdrücken verwenden. Aber hier übergeben wir einfach den Parameter an die PipeTo() -Methode und es werden keine Closures erzeugt. – alexey

+3

Sender ist eine kontextsensitive Methode - der Wert mutiert jedes Mal, wenn eine Nachricht von einem Akteur empfangen wird. Wenn der aktuelle Wert von Sender nicht in einer lokalen Variable zwischengespeichert wird, die bei der Verwendung von PipeTo geschlossen wird, besteht die große Chance, dass Ihr Sender-Aufruf einen anderen Wert als den von Ihnen erwarteten zurückgibt. Wir konnten diesen Fehler mehrfach replizieren: p – Aaronontheweb

+0

@Aaronontheweb: "Wenn der aktuelle Wert von Absender nicht in einer lokalen Variablen zwischengespeichert wird, die geschlossen wird, wenn Sie PipeTo verwenden". Das ergibt für mich keinen Sinn: Was PipeTo macht, ist nicht die Eigenschaft 'Sender', sondern eine lokale Variable (das Argument' recipient'), die eine Kopie des Verweises auf den aktuellen 'Sender' ist. Daher sehe ich das nicht anders als das explizite Kopieren der Eigenschaft 'Sender' in eine lokale Variable. –

Verwandte Themen