public static void DownloadAndConvertHistoricalData(object downloadParams) { Variables.DownloadedCount = 0; // track downloads Variables.threadList.Clear(); HistoricalDownloadParams _downloadParams = downloadParams as HistoricalDownloadParams; if (_downloadParams.StartDownloadProcess != null) { _downloadParams.StartDownloadProcess(); } List <string> tmpList = new List <string>(); tmpList.AddRange(_downloadParams.stockList.ToArray()); const int NUM_THREADS = 5; int stockCount = tmpList.Count; int threadCount = stockCount / NUM_THREADS; if (threadCount == 0) { threadCount = 1; } int startIndex = 0; int adder = 0; for (int i = 0; i < threadCount; i++) { // add the remainder of the stocks in the list if (threadCount == i + 1) { adder = stockCount % NUM_THREADS; } int downloadItemCount = (stockCount >= NUM_THREADS) ? NUM_THREADS + adder : adder; // take the items List <string> l = new List <string>(); l.AddRange(tmpList.Take(downloadItemCount).ToArray()); DoDownloadHistoricalData(l, _downloadParams.NumYears, _downloadParams.OutputSettings, _downloadParams.BeforeStockDataDownloadCallback, _downloadParams.AfterStockDataDownloadCallback, _downloadParams.OnExceptionCallback); // remove added items tmpList.RemoveRange(startIndex, downloadItemCount); } // wait for everything to complete while (true) { int count = (from t in Variables.threadList where t.IsAlive == true select t).Count(); if (count == 0) { if (_downloadParams.DownloadAllCompleteCallback != null) { _downloadParams.DownloadAllCompleteCallback(); } break; } } }