Domanda

In un'applicazione a cui sto lavorando, migliaia di aggiornamenti vengono ricevuti al secondo.Riflettendo questi aggiornamenti sull'interfaccia utente immediatamente e uno per uno è overkill sulle prestazioni.

Il seguente codice produce prestazioni molto cattive, poiché la gestione di ogni aggiornamento richiede di richiamare la filettatura dell'interfaccia utente e aggiungere un nuovo elemento a un osservableCollection che a turno scatena l'evento CollectionChanged.

foreach (var update in updates.GetConsumingEnumerable())
{
    // Handle Update
}
.

Che cosa sto cercando di fare è rendere il consumatore ad aspettare un po 'di tempo (cioè 50 millisecond) per dare un'opportunità per l'editore per aggiungere altri oggetti, quindi gestire questi aggiornamenti in blocchi. Attualmente, sto usando il seguente codice, ma trovo difficile prevedere per quanto tempo gli articoli rimarranno nella collezione prima di essere consumati, temo che questo approccio possa produrre un altro collo di bottiglia di performance.

List<Tuple<T, List<string>>> updatesToHandle = new List<Tuple<T, List<string>>>();
while (!updates.IsAddingCompleted)
{
    Tuple<T, List<string>> item = null;
    if (updates.TryTake(out item, 5)) // Try Take for 5 Milliseconds
    {
        updatesToHandle.Add(item);
    }
    else
    {
        var newItems = new List<T>(updatesToHandle.Count);
        var updatedItems = new List<Tuple<T, List<string>>>(updatesToHandle.Count);
        foreach (var update in updatesToHandle)
        {
            try
            {
                // Handle Update
            }
            finally
            {
                updatesToHandle.Clear();
                Thread.Sleep(50);
            }
        }
    }
}
.

È stato utile?

Soluzione

Considererei l'utilizzo di estensioni reattive reattivestensions .Questo collegamento risolve un problema simile Esempio di negoziazione Stock

Altri suggerimenti

Suggerirei due modifiche al tuo codice.

Prima, piuttosto che avere il filo del filo, creare un timer che spara ogni 50 millisecondi.Quel gestore del timer loop poi su TryTake senza ritardi, raccogliendo tutti gli elementi che sono attualmente nella raccolta (o fino ad un po 'di massimo).Senza ritardo, TryTake tornerà immediatamente se la raccolta è vuota.

Secondo, non chiamare la "UI aggiorna" una volta per ogni aggiornamento.Modificare il gestore di aggiornamento in modo che accetti l'intero elenco di aggiornamenti piuttosto che un aggiornamento alla volta.Ciò eviterà il tempo necessario in attesa del filo dell'interfaccia utente.

Quanto sopra assume, ovviamente, che hai modificato il gestore di aggiornamento in modo che possa aggiungere più elementi al ObservableCollection in un colpo, evitando più eventi CollectionChanged.

I secondo rx.In particolare, si desidera il bufferytime (se si aggrega quando la velocità in entrata è alta) o l'acceleratore (se lanciando i valori in uscita quando la velocità in entrata è troppo alta).Inoltre, il tuo Ui dovrebbe probabilmente essere vincolato a comportamenti di studio, che cacherà sempre l'ultimo valore in modo che i nuovi abbonati ottengano quell'ultimo valore memorizzato nella cache immediatamente quando si iscrivono.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top