Я бы предложил создать BlockingCollection (очередь) рабочих элементов и таймер, который вызывает базу данных каждые 30 секунд для ее заполнения.Что-то вроде:
BlockingCollection<WorkItem> WorkItems = new BlockingCollection<WorkItem>();
И при инициализации:
System.Threading.Timer WorkItemTimer = new Timer((s) =>
{
var items = WorkItemRepository.GetItemList(); //database call
foreach (var item in items)
{
WorkItems.Add(item);
}
}, null, 30000, 30000);
Это будет запрашивать базу данных для элементов каждые 30 секунд.
Для планирования рабочих элементов, которые будут обрабатыватьсяУ вас есть несколько разных решений.Самое близкое к тому, что у вас есть, это:
WorkItem item;
while (WorkItems.TryTake(out item, Timeout.Infinite, _cancellation))
{
Task.Factory.StartNew((s) =>
{
var myItem = (WorkItem)s;
// process here
}, item);
}
Это устраняет блокировки в любом из потоков и позволяет TPL решить, как лучше распределить параллельные задачи.
РЕДАКТИРОВАТЬ:
На самом деле, ближе к тому, что у вас есть:
foreach (var item in WorkItems.GetConsumingEnumerable(_cancellation))
{
// start task to process item
}
Вы можете использовать:
Parallel.Foreach(WorkItems.GetConsumingEnumerable(_cancellation).AsParallel ...
Я не знаю, будет ли это работать или какЧто ж.Может стоит попробовать.,.
END OF EDIT
В общем, я предлагаю вам рассматривать это как приложение производителя / потребителя, причем производитель является потоком, который периодически запрашивает у базы данных новые элементы.,Мой пример запрашивает базу данных один раз каждые N (в нашем случае 30) секунд, что будет хорошо работать, если в среднем вы будете очищать свою рабочую очередь каждые 30 секунд.Это даст среднюю задержку менее минуты с момента публикации элемента в базе данных до получения результатов.
Вы можете уменьшить частоту опроса (и, следовательно, задержку), но это приведет кбольше трафика базы данных.
С этим вы тоже можете полюбить.Например, если вы опрашиваете базу данных через 30 секунд и получаете огромное количество элементов, то, скорее всего, вы получите больше в ближайшее время, и вам захочется повторить опрос через 15 секунд (или меньше).И наоборот, если вы опрашиваете базу данных через 30 секунд и ничего не получите, то, вероятно, вы сможете подождать, прежде чем снова начать опрос.
Вы можете настроить этот тип адаптивного опроса, используя таймер с одним выстрелом.То есть вы указываете -1 для последнего параметра при создании таймера, который вызывает его срабатывание только один раз.Ваш обратный вызов таймера определяет, как долго ждать до следующего опроса, и вызывает Timer.Change
, чтобы инициализировать таймер новым значением.