Wie kann ich den Puffer auf einem ReplaySubject löschen?

8

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.

    
CodingHero 09.03.2015, 14:56
quelle

2 Antworten

9

ReplaySubject bietet keine Möglichkeit, den Puffer zu löschen, aber es gibt mehrere Überladungen, die die Puffer auf unterschiedliche Weise einschränken:

  • Ein maximales TimeSpan , für das Elemente für
  • beibehalten werden
  • Eine maximale Anzahl an Artikeln
  • Eine Kombination der oben genannten Elemente, die Elemente löscht, sobald eine der Bedingungen erfüllt ist.

Ein korrigierbares ReplaySubject

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 :

%Vor%

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 .

Verbesserungen

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: Ссылка

    
James World 09.03.2015, 15:13
quelle
0

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.

    
Lee Oades 24.03.2015 13:31
quelle

Tags und Links