Ради интереса откопал изначальную версию кода:
C#:
while (true)
{
if (queue.Count < 1) continue;
else
MySQL.Query(queue.Dequeue());
}
Да, действительно, такого вида while(true) приведёт к сжиранию 100% CPU thread'а, так как проверка содержимого очереди будет проходить бесконечно.
Классическое решение этой проблемы — добавление Thread.Sleep(), который разгрузит процессор и укажет шедулеру, что данный поток/воркер не нужно выполнять на CPU в течение долгого времени. Получается, что код можно поправить всего лишь несколькими строчками:
C#:
while (true)
{
/* Sleep if queue is empty */
if (queue.Count < 1)
{
Thread.Sleep(500);
continue;
}
/* Run all queries from queue */
while (queue.Any())
MySQL.Query(queue.Dequeue());
}
В итоге мы получим примерно тот же самый результат, что и у автора темы, но с минимальными изменениями оригинального кода и сохранив его простоту, при этом значительно оптимизировав.
Однако что решение с таймером, что с sleep'ом страдает от одной и той же проблемы: всегда будет совершенно ненужная задержка с момента добавления новой строки в очередь логов, варьирующаяся от 0 до 500 мс.
На мой взгляд, наилучшем решением будет использование
BlockingCollection<string> вместо Queue<string>. Тогда вместо queue.Dequeue() мы будем вызывать bc.Take(), который «заблокирует» тред, т.е. переведет его в blocking state, а значит
а) тред не будет израсходывать CPU time до того момента, пока в коллекцию не придёт новый элемент
б) ОС мгновенно разблокирует тред в момент, когда какой-либо другой тред таки добавит в нашу новую «очередь», построенную на BlockingCollection, новое значение, а значит и добавление новых логов в БД произойдёт мгновенно.
Таким образом, код можно упростить практически до (конечно, стоило бы проверить вернувшееся значение из .Take() и обернуть это в try catch{}, как это сделано в примере из документации выше):
C#:
while (true)
{
MySQL.Query(bc.Take());
}