2015-07-10 7 views
5

Ecco the official sample di utilizzare PipeTo() in Akka.NET:Perché dovrei usare la chiusura mittente con 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); 
}); 

La domanda è: perché dovremmo usare Sender chiusura qui? Perché non usare solo:

In questo esempio e nei documenti si dice che è obbligatorio utilizzare la chiusura qui. Ma non vedo alcun motivo per farlo.

Se si utilizza ContinueWith() è ragionevole utilizzare la chiusura all'interno della continuazione, ma non come parametro PipeTo().

Mi manca qualcosa?

risposta

5

due cose da capire qui:

  1. Sender non è una proprietà statica. Sender is actually a function on the IActorContext che restituisce il mittente del messaggio corrente in fase di elaborazione. Il valore restituito cambia ogni volta che il contesto riceve un nuovo messaggio dalla casella di posta.

  2. PipeTo è una continuazione, e quando la continuazione eseguito sul ThreadPool, chiamando Sender avrà accesso alla stessa identica IActorContext oggetto che ha iniziato l'attività. Non vi è alcuna garanzia che l'attuale Sender nel contesto sia lo stesso, poiché i nuovi messaggi vengono inseriti nell'attore per l'elaborazione dall'avvio dell'attività.

Così abbiamo cache il valore della Sender in una variabile locale per garantire che noi stiamo puntando PipeTo alla giusta IActorRef ogni volta che viene eseguito.

+1

Il problema che descrivi appare quando il compilatore acquisisce "questo" in un contesto di chiusura. Ad esempio, accade quando utilizziamo "questo" membri (come Sender) nelle espressioni lambda. Ma qui passiamo il parametro al metodo PipeTo() e non ci sono chiusure create. – alexey

+3

Il mittente è un metodo sensibile al contesto: il suo valore si modifica ogni volta che un messaggio riceve un messaggio. Se il valore corrente di Sender non è memorizzato nella cache di una variabile locale, che viene chiusa quando si utilizza PipeTo, c'è una forte possibilità che la chiamata del mittente possa restituire un valore diverso dall'attore che ci si aspetta. Siamo stati in grado di replicare questo errore numerose volte: p – Aaronontheweb

+0

@Aaronontheweb: "Se il valore corrente di Sender non è memorizzato nella cache in una variabile locale, che viene chiusa quando si utilizza PipeTo". Questo non ha senso per me: ciò che PipeTo fa non è la chiusura sulla proprietà 'Sender' ma su una variabile locale (l'argomento' recipient') che è una copia del riferimento al corrente 'Sender'. Pertanto non vedo questo come diverso dalla copia esplicita della proprietà 'Sender' su una variabile locale. –