Si consideri il seguente:Perché RefCount non funziona dopo che tutti gli abbonati iniziali si sono scollegati?
[Fact]
public void foo()
{
var result = new Subject<bool>();
var startCount = 0;
var completionCount = 0;
var obs = Observable
.Defer(() =>
{
++startCount;
return result.FirstAsync();
})
.Do(_ => ++completionCount)
.Publish()
.RefCount();
// pretend there are lots of subscribers at once
var s1 = obs.Subscribe();
var s2 = obs.Subscribe();
var s3 = obs.Subscribe();
// even so, we only expect to be started once
Assert.Equal(1, startCount);
Assert.Equal(0, completionCount);
// and we won't complete until the result ticks through
result.OnNext(true);
Assert.Equal(1, startCount);
Assert.Equal(1, completionCount);
s1.Dispose();
s2.Dispose();
s3.Dispose();
// now try exactly the same thing again
s1 = obs.Subscribe();
s2 = obs.Subscribe();
s3 = obs.Subscribe();
// startCount is 4 here instead of the expected 2!
Assert.Equal(2, startCount);
Assert.Equal(1, completionCount);
result.OnNext(true);
Assert.Equal(2, startCount);
Assert.Equal(2, completionCount);
s1.Dispose();
s2.Dispose();
s3.Dispose();
}
mia comprensione di Publish
+ RefCount
è che una connessione alla sorgente viene mantenuta finché c'è almeno un utente. Una volta che l'ultimo utente si disconnette, qualsiasi utente futuro riavvierà la connessione alla fonte.
Come potete vedere nel mio test, tutto funziona alla perfezione. Ma la seconda volta, il rinviabile osservabile all'interno della pipeline viene eseguito una volta per ogni nuovo abbonato.
Vedo tramite il debugger che per il primo gruppo di abbonati, obs._count
(che conta gli abbonati) aumenta per ogni chiamata a Subscribe
. Ma per il secondo gruppo di abbonati, rimane zero.
Perché sta succedendo questo e cosa posso fare per rettificare la mia pipeline?
Sembra plausibile, ma ho difficoltà a produrre una sequenza che funzioni come previsto. Ho pensato che 'return result.Take (1);' piuttosto che 'return result.FirstAsync();' avrebbe funzionato, ma sto ottenendo lo stesso risultato. Piuttosto curioso., – Enigmativity
'result' ha _not_ completato. Ogni singola chiamata a 'result.FirstAsync' verrà completata quando si seleziona un nuovo valore. –
Avrei dovuto dire result.FirstAsync ha completato. Sono d'accordo sul fatto che il comportamento sia strano. Sembra che questo sia in qualche modo catturato in modo che i futuri abbonati recuperino l'osservabile completato.Puoi vederlo collegando il tuo secondo set di sottoscrittori agli eventi OnCompleted, che si attivano immediatamente piuttosto che aspettare che tu invii un altro .OnNext. Quindi ogni nuovo iscritto incrementa il conteggio. – user630190