Wie kann ich den Puffer auf einem ReplaySubject löschen?
In regelmäßigen Abständen muss ich den Puffer löschen (in meinem Fall ein Ereignis am Ende des Tages), um zu verhindern, dass das ReplaySubject ständig wächst und schließlich den gesamten Speicher verbraucht.
Idealerweise möchte ich das gleiche ReplaySubject behalten, da die Client-Abonnements immer noch gut sind.
danke.
ReplaySubject
bietet keine Möglichkeit, den Puffer zu löschen, aber es gibt mehrere Überladungen, die die Puffer auf unterschiedliche Weise einschränken:
TimeSpan
, für das Elemente für Das war ein ziemlich interessantes Problem - ich entschied zu sehen, wie einfach es wäre, eine Variation von ReplaySubject
zu implementieren, die Sie löschen können - indem Sie vorhandene Subjekte und Operatoren verwenden (da diese ziemlich robust sind) . Es stellte sich heraus, dass es einigermaßen unkompliziert war.
Ich habe dies durch einen Speicherprofiler laufen lassen, um zu überprüfen, ob es richtig ist. Rufen Sie Clear()
auf, um den Puffer zu löschen, andernfalls funktioniert es wie ein reguläres unbegrenztes ReplaySubject
:
Respektiere die üblichen Regeln (wie bei Subject
) und rufe nicht gleichzeitig Methoden für diese Klasse auf - einschließlich Clear()
. Sie können Synchronisierungssperren bei Bedarf trivial hinzufügen.
Es funktioniert, indem Sie eine Sequenz von ReplaySubjects in einem Master ReplaySubject verschachteln. Das äußere ReplaySubject ( _subjects
) enthält einen Puffer mit genau einem inneren ReplaySubject ( _currentSubject
) und wird bei der Konstruktion ausgefüllt.
Die Methoden OnXXX
rufen bis zum _currentSubject
ReplaySubject auf.
Beobachter haben eine verkettete Projektion der verschachtelten ReplaySubjects abonniert (in _concatenatedSubjects
). Da die Puffergröße von _subjects
nur 1 ist, erfassen neue Abonnenten die Ereignisse nur der letzten ReplaySubject
ab.
Wann immer wir den Puffer löschen müssen, ist das vorhandene _currentSubject
OnCompleted
und ein neues ReplaySubject wird zu _subjects
hinzugefügt und wird zum neuen _currentSubject
.
Nach dem Vorschlag von @ Brandon habe ich eine Version von RollingReplaySubject
erstellt, die entweder einen TimeSpan
oder einen Eingabestream verwendet, um das Buffer-Clearing zu signalisieren. Ich habe dafür einen Gist erstellt: Ссылка
Wahrscheinlich haben Sie bereits eine beobachtbare Datenquelle. In diesem Fall ist hier eine andere Lösung. Dieser verwendet die Zusammensetzung existierender RX-Konstrukte, anstatt ein eigenes ISubject zu erstellen, von dem ich persönlich vorsichtig bin.
%Vor%Wenn Sie Ihrem ObservableEx die folgende Erweiterungsmethode hinzufügen:
%Vor%Dann kannst du deine Quelle nehmen und .ReplayWithReset (...) mit deinem Reset-Trigger Observable hinzufügen. Dies könnte ein Timer oder was auch immer sein.
%Vor%Die Verbindung verhält sich genauso wie eine Wiederholung.
Tags und Links c# system.reactive