Updating grid with 1000+ updates every second

Topics: Prism v4 - WPF 4
May 5, 2015 at 9:37 PM
Edited May 5, 2015 at 9:39 PM
Hi

I am getting my head around RX and introducing it into our WPF MVVM designed application.

The problem

The problem that I have is that data is appearing too fast into the GRID and I would like a way to buffer the data so that the grid and ultimately the UI is responsive. Ideally I would like a way to (say) update the grid every 'x' seconds with only 'y' records at a time.

I realise we can use :

sequenceOfTradeUpdates.Buffer(TimeSpan.FromSeconds(1),10)... etc but this will not ensure that we release exactly 10 updates to the grid ONLY within a 1 (say second window) because this version of Buffer will wait at most 1 seconds OR if it gets 10 items. If 10 items (say) occurs within less that 1 second it will run the subscription code which isnt what we want. We need to ensure EXACTLY 'x' milliseconds is waited and then release at most 10 rows and thats the part where I'm stuck.

Our Shared Service Process

We have a process that is constantly running which produces trade level information based on latest pricing information for one or more ticker codes. The process raises an event for which one or more subscribers subscribe to. This process can produce (say) 1000 updates of new pricing information every 300-1000 milliseconds.

The event that this process raises is defined as :
public IObservable<IBlotter> BlotterUpdates
    {
        get
        {
            return Observable.FromEventPattern<IBlotter>(
                evt => BlotterEvent += evt,
                evt => BlotterEvent -= evt
                ).Select(i=>i.EventArgs).AsObservable<IBlotter>();
        }
    }
Where IBlotter can be some thing as simple as :

double LatestPrice
string Ticker

Our ViewModel

Our ViewModel subscribes to this shared service in this way ;

var obs = services.BlotterUpdates
                  .Buffer(TimeSpan.FromSeconds(1000), 10)                     
                  .SubscribeOn(Scheduler.Default)
                  .Subscribe(item=>{
                      foreach (var i in item)
                      {                           
                         UpdateGridWithThisBlotterItem((i);
                      }

Running the code above , the UI updates but the UI is almost non responsive. We still get too many updates every second. If we change the above to :



var obs = services.BlotterUpdates
                  .Buffer(TimeSpan.FromSeconds(1000), 10)                     
                  .SubscribeOn(Scheduler.Default)
                  .Subscribe(item=>{
                      foreach (var i in item)
                      {                           
                         Thread.Sleep(600);
                         UpdateGridWithThisBlotterItem((i);
                      }
i.e we add an IMPLICIT SLEEP before the update , then the UI is responsive and updates without causing any issue BUT this isnt the desired functionality as we need to ensure we update every 'x' milliseconds and at most 'y' records.

Furthermore, if we changed the shared service to Sleep (say) every second after it posts an event then this also allows the grid to become responsive but again , this defeats the object of the original problem and we dislike adding artificial sleeps within a pub/sub designed application.


Is there something we are missing ?

Thanks

Stella
May 6, 2015 at 3:04 AM
If you're using Reactive (RX), why not use PRISM with ReactiveUI? http://reactiveui.net/ I use ReactiveUI + PRISM for software that I develop for work. If you use IObserver or IObservable, why not consider using a framework built around that? Reactive has mechanisms built in that handle updates via the IObservable / IObserver pattern.

To answer your question, you may want to use https://msdn.microsoft.com/en-us/library/system.reactive.linq.observable.throttle%28v=vs.103%29.aspx Throttle, as it is designed to throttle the number of updates. Linq for RX is very powerful.
May 6, 2015 at 6:45 AM

Issue with throttling

Cant use throttle as each update that comes in must be used in a further computation that is required for a graphing component , so throttling in this situation is not useful as we cant miss a single update .