private WeightedWorkScheduler()
        {
            _newWork      = new ConcurrentQueue <WorkItem>();
            _newWorkEvent = new AutoResetEvent(false);

            var work         = new List <WorkQueue>();
            var queueManager = new Thread(() =>
            {
                var workersCount = Configuration.Config.GetInt("data-feed-workers-count", Environment.ProcessorCount);
                MaxWorkWeight    = Configuration.Config.GetInt("data-feed-max-work-weight", 400);
                Logging.Log.Trace($"WeightedWorkScheduler(): will use {workersCount} workers and MaxWorkWeight is {MaxWorkWeight}");

                for (var i = 0; i < workersCount; i++)
                {
                    var workQueue = new WorkQueue();
                    work.Add(workQueue);
                    var thread = new Thread(() => WorkerThread(workQueue, _newWork, _newWorkEvent))
                    {
                        IsBackground = true,
                        Priority     = ThreadPriority.Lowest,
                        Name         = $"WeightedWorkThread{i}"
                    };
                    thread.Start();
                }

                // make sure that the WorkQueue are kept sorted and the weights up to date
                while (true)
                {
                    Thread.Sleep(TimeSpan.FromMilliseconds(1));
                    foreach (var queue in work)
                    {
                        queue.Sort();
                    }
                }
            })
            {
                IsBackground = true,
                Name         = "WeightedWorkManager"
            };

            queueManager.Start();
        }
        /// <summary>
        /// This is the worker thread loop.
        /// It will first try to take a work item from the new work queue else will check his own queue.
        /// </summary>
        private static void WorkerThread(WorkQueue workQueue, ConcurrentQueue <WorkItem> newWork, AutoResetEvent newWorkEvent)
        {
            var waitHandles = new WaitHandle[] { workQueue.WorkAvailableEvent, newWorkEvent };

            while (true)
            {
                WorkItem workItem;
                if (!newWork.TryDequeue(out workItem))
                {
                    workItem = workQueue.Get();
                    if (workItem == null)
                    {
                        // no work to do, lets sleep and try again
                        WaitHandle.WaitAny(waitHandles, 100);
                        continue;
                    }
                }
                else
                {
                    workQueue.Add(workItem);
                }

                try
                {
                    if (!workItem.Work(WorkBatchSize))
                    {
                        workQueue.Remove(workItem);
                    }
                }
                catch (Exception exception)
                {
                    workQueue.Remove(workItem);
                    Logging.Log.Error(exception);
                }
            }
        }