public List <DailyPrice> GetPrices() { _logger.Information("Initializing price retriever..."); _retrieved.Clear(); // this AutoResetEvent is 'shared' by the calling method and the data retrieval method // and is used to indicate when all available SecurityInfo objects have been processed var jobDone = new AutoResetEvent(false); var interval = Convert.ToInt32(60000 / _config.CallsPerMinute); _currentRetrieval = CurrentRetrieval.Prices; // this creates the timer and starts it running _timer = new Timer(ProcessNextSymbol, jobDone, 0, interval); // wait until the processing is done jobDone.WaitOne(); _logger.Information("Price retrieval complete"); return(_retrieved.Select(kvp => kvp.Value) .ToList()); }
public void ProcessNextSymbol(object?stateInfo) { // wrap the call to the actual processing method in a monitor to // prevent multiple simultaneous accesses to the DbContext object if (Monitor.TryEnter(_lockObject)) { try { // check to ensure we were given the AutoResetEvent we're expecting var jobDone = stateInfo as AutoResetEvent; if (jobDone == null) { _logger.Error($"Argument is not a {nameof( AutoResetEvent )}"); } else { switch (_currentRetrieval) { case CurrentRetrieval.Prices: RetrievePriceData(jobDone); _currentRetrieval = CurrentRetrieval.Name; break; case CurrentRetrieval.Name: RetrieveSymbolInfo(jobDone); _currentRetrieval = CurrentRetrieval.Prices; _index++; break; } if (_index >= _config.Securities.Count) { jobDone.Set(); } } } finally { Monitor.Exit(_lockObject); } } }