2015-07-10 9 views
5

Oto the official sample korzystania PipeTo() w Akka.NET:Dlaczego powinienem używać zamknięcia nadawcy za pomocą PipeTo()?

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

Powstaje pytanie, dlaczego powinniśmy używać Sender zamknięcie tutaj? Dlaczego nie skorzystać po prostu:

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

W tej próbce oraz w dokumentach jest powiedziane, że obowiązkowe jest tutaj zamknięcie. Ale nie widzę powodów, by to robić.

Jeśli użyliśmy ContinueWith(), rozsądnie jest użyć zamknięcia wewnątrz kontynuacji, ale nie jako parametru PipeTo().

Czy coś mi brakuje?

Odpowiedz

5

dwie rzeczy rozumieć tutaj:

  1. Sender nie jest obiektem statycznym. Sender is actually a function on the IActorContext, która zwraca nadawcę aktualnie przetwarzanej wiadomości. Zwrócona wartość zmienia się za każdym razem, gdy kontekst pobiera nową wiadomość ze skrzynki pocztowej.

  2. PipeTo jest kontynuacją, a gdy to kontynuacja wykonuje na puli wątków, nazywając Sender uzyska dostęp do dokładnie tego samego IActorContext obiekt, który rozpoczął zadanie. Nie ma gwarancji, że bieżący numer Sender w tym samym kontekście jest taki sam, ponieważ nowe wiadomości zostały przesłane do aktora w celu przetworzenia od rozpoczęcia zadania.

Więc buforować wartość Sender w zmiennej lokalnej w celu zagwarantowania, że ​​naszym celem PipeTo w odpowiednim IActorRef gdy wykonuje on.

+1

Problem, który opisujesz pojawia się, gdy kompilator przechwytuje "to" w kontekście zamknięcia. Na przykład dzieje się, gdy używamy "tych" członków (takich jak nadawca) w wyrażeniach lambda. Ale tutaj po prostu przekazujemy parametr do metody PipeTo() i nie tworzy się zamknięć. – alexey

+3

Nadawca jest metodą kontekstową - jego wartość zmienia się za każdym razem, gdy aktor odbierze wiadomość. Jeśli bieżąca wartość nadawcy nie jest buforowana w zmiennej lokalnej, która zostanie zamknięta podczas korzystania z PipeTo, istnieje duża szansa, że ​​połączenie nadawcy może zwrócić wartość inną niż oczekiwany aktor. Wielokrotnie mogliśmy powtórzyć ten błąd: p – Aaronontheweb

+0

@Aaronontheweb: "Jeśli bieżąca wartość nadawcy nie jest zapisana w pamięci podręcznej w zmiennej lokalnej, która zostanie zamknięta podczas korzystania z PipeTo". Nie ma to dla mnie sensu: to, co robi PipeTo, nie zamyka się na właściwości 'Sender', ale na zmiennej lokalnej (argument' recipient'), która jest kopią odwołania do bieżącego 'Sendera'. Dlatego nie uważam tego za coś innego niż jawne kopiowanie właściwości 'Sender' do zmiennej lokalnej. –

Powiązane problemy