Q: Зачем это?
A: Библиотека содержит расширяемый набор классов и интерфейсов, представляющих для .NET разработчика простой инструмент для реализации собственной СМО.
Q: Пример использования?
A: Например, Вы пишете приложение которое принимает из сети пакеты, фильтрует, разбирает и складывает их в базу, при этом, каждый из перечисленных шагов выносится в отдельную СМО (отдельный(-ые) поток(и) со своей очередью). Обработка задач из очереди на каждом шаге происходит независимо от других шагов в отдельном потоке, что позволяет достичь максимальной производительности системы целиком.
Q: Как устроена?
A: Основу библиотеки NQueueing представляет интерфейс IServerQueue.

Интерфейс является generic-типом, и типизируется типом задачи. Все обработчики очередей реализуют данный интерфейс.
Уровнем выше, находится абстрактный базовый класс для всех обработчиков очередей ServerQueueBase, инкапсулирующий в себя общие свойства любой СМО (например: объект очередь и массив потоков).
Следующий уровень абстракции - это конкретные реализации различных типов СМО, унаследованные от ServerQueueBase классы: StandartServerQueue (для поштучной обработки задач из очереди) и BatchServerQueue (для пакетной обработки):

Q: Как использовать?
A: Использовать библиотеку достаточно просто:
- Скачать библиотеку.
- Добавить на нее reference в проекте. После чего станет доступен namespace NQueueing.
- В зависимости от типа задачи, выбрать соответствующий тип СМО (StandartServerQueue, BatchServerQueue итп).
- Далее создать экземпляр СМО (выбранной на предыдущем шаге), передав в конструктор ссылку на делегат, в котором и описывается процесс обработки пришедшей задачи, и указав параметры СМО: длина очереди, число потоков обработки.
- При помощи потоко-безопасных TryEnqueue/Enqueue ставить задачи в очередь.
using System;
using System.Threading;
// Добавить reference на библиотеку
using NQueueing;
namespace NQueueingTestApp
{
class Program
{
// Имитация случайной задержки
static Random rnd = new Random(DateTime.Now.Millisecond);
static void RandomSleep(int min, int max)
{
Thread.Sleep(rnd.Next(min, max));
}
static void ProcessingOne(int item)
{
// Обработать здесь задачу item...
// Обработка происходит в отдельном потоке.
RandomSleep(10, 300); // Случайная задержка в обработке
// Номер текущего потока, от 0 до (maxThreadsCount-1)
string name = Thread.CurrentThread.Name;
Console.WriteLine("{0} / Thread №: {1}", item, name);
}
static void Main(string[] args)
{
// Создадим Систему Массового Обслуживания состоящую
// из 3-х потоков и очередью длины 10.
IServerQueue<int> smo = new StandartServerQueue<int>(ProcessingOne, 10, 3);
smo.Start(); // Запускаем процесс обработки
// Добавим 15 задач в очередь
for (int task = 0; task < 15; task++)
{
// Поставим задачу в очередь в текущем потоке
EnqueueStatus result = smo.TryEnqueue(task);
RandomSleep(10, 100); // Случайная задержка при добавлении
Console.WriteLine("{0} / Enqueue: {1}", task, result);
}
smo.Close(); // Не забываем остановить
Console.ReadKey();
}
}
}
Q: Расширяемость?
A: Да, такая возможность есть. Для этого необходимо реализовать интерфейс IServerQueue, либо реализовать наследника от базового класса ServerQueueBase.
Буду благодарен за Ваши отзывы, рекомендации и конструктивные советы.
Ссылки:
20 коммент.: