ManualResetEvent vs. Thread.Sleep

J'ai mis en œuvre dans le contexte suivant thread de traitement, où Jobs est un Queue<T>:

static void WorkThread()
{
    while (working)
    {
        var job;

        lock (Jobs)
        {
            if (Jobs.Count > 0)
                job = Jobs.Dequeue();
        }

        if (job == null)
        {
            Thread.Sleep(1);
        }
        else
        {
            //[snip]: Process job.
        }
    }
}

Ce produit un notable retard entre le moment où les travaux ont été saisies et quand ils étaient en train de commencer à être exécuté (lots de travaux sont inscrits à la fois, et chaque travail est seulement [relativement] petit). Le retard n'était pas une affaire énorme, mais j'ai eu à réfléchir au problème, et apporté la modification suivante:

static ManualResetEvent _workerWait = new ManualResetEvent(false);
//...
    if (job == null)
    {
        lock (_workerWait)
        {
            _workerWait.Reset();
        }
        _workerWait.WaitOne();
    }

Où le fil de l'ajout des emplois dès maintenant serrures _workerWait et les appels _workerWait.Set() quand c'est fait, l'ajout d'emplois. Cette solution de (presque) instantanément commence les travaux de traitement, et le retard est disparu complètement.

Ma question est en partie "Pourquoi cela?", accordé que Thread.Sleep(int) peut très bien dormir plus longtemps que vous spécifiez, et en partie "Comment le ManualResetEvent atteindre ce niveau de performance?".

EDIT: Depuis quelqu'un a demandé à propos de la fonction de mise en queue des articles, c'est ici, le long avec un système complet en ce moment.

public void RunTriggers(string data)
{
    lock (this.SyncRoot)
    {
        this.Triggers.Sort((a, b) => { return a.Priority - b.Priority; });

        foreach (Trigger trigger in this.Triggers)
        {
            lock (Jobs)
            {
                Jobs.Enqueue(new TriggerData(this, trigger, data));
                _workerWait.Set();
            }
        }
    }
}

static private ManualResetEvent _workerWait = new ManualResetEvent(false);
static void WorkThread()
{
    while (working)
    {
        TriggerData job = null;

        lock (Jobs)
        {
            if (Jobs.Count > 0)
                job = Jobs.Dequeue();

            if (job == null)
            {
                _workerWait.Reset();
            }
        }

        if (job == null)
            _workerWait.WaitOne();
        else
        {
            try
            {
                foreach (Match m in job.Trigger.Regex.Matches(job.Data))
                    job.Trigger.Value.Action(job.World, m);
            }
            catch (Exception ex)
            {
                job.World.SendLineToClient("\r\n\x1B[32m -- {0} in trigger ({1}): {2}\x1B[m",
                    ex.GetType().ToString(), job.Trigger.Name, ex.Message);
            }
        }
    }
}

source d'informationauteur Matthew Scharley