/// <summary> /// dispatcher timer to update prices for each ticker, uses fast tick rate to animate price changes /// </summary> private void StartPriceUpdatingDispatcherTimer() { _updateTimer = new DispatcherTimer(); _updateTimer.Interval = TimeSpan.FromMilliseconds(_animateIntervalMillis); _updateTimer.Tick += (sender, e) => { //larger interval - check API for new prices if (_currentIntervalCount == _updateInterval) { _currentIntervalCount = 0; //choose random batch of tickers to update _currentTickerBatchIndices = new int[_tickerBatchCount]; for (int i = 0; i < _tickerBatchCount; i++) { //if queue is empty, ticker update cycle has completed, //so first remove any unwanted tickers and update portions //then create new random ticker order //***NOTE*** this can create redundant coins in a ticker batch due to wrap-around if (_randomIndexQueue.Count == 0) { for (int tickerIndex = 0; tickerIndex < Tickers.Count; tickerIndex++) { if (Tickers[tickerIndex].RemoveRequested == true) { Tickers.RemoveAt(tickerIndex); tickerIndex--; } else { UpdatePortion(Tickers[tickerIndex]); } } CreateRandomTickerUpdateOrder(); } _currentTickerBatchIndices[i] = _randomIndexQueue.Dequeue(); } //update the current batch of tickers UpdateTickers(_currentTickerBatchIndices); //update the USD total UpdateTotal(); if (NewCoinBackgroundColor != "#CCC") { NewCoinBackgroundColor = "#CCC"; } } //smaller interval - otherwise check if any prices need to be animated else { _currentIntervalCount++; foreach (int tickerIndex in _currentTickerBatchIndices) { if (Tickers[tickerIndex].IsAnimating) { Tickers[tickerIndex].AnimateMoveTowardNewPrice(); } } } }; _updateTimer.IsEnabled = true; }