ManualResetEvent vs. Thread.Sleep

Zaimplementowałem następujący wątek przetwarzania w tle, gdzieJobs jestQueue<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.
        }
    }
}

Spowodowało to zauważalne opóźnienie między wprowadzeniem zadań a ich uruchomieniem (partie zadań są wprowadzane od razu, a każde zadanie jest tylko [względnie] małe.) Opóźnienie nie było wielką transakcją, ale myślałem o problemie i wprowadziłem następującą zmianę:

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

Gdzie wątek dodający zadania teraz się blokuje_workerWait i połączenia_workerWait.Set() kiedy skończysz dodawać zadania. To rozwiązanie (pozornie) natychmiast rozpoczyna przetwarzanie zadań, a opóźnienie całkowicie mija.

Moje pytanie jest częściowo „Dlaczego tak się dzieje?”, Przyznało toThread.Sleep(int) może bardzo dobrze spać dłużej niż określiłeś, a częściowo „JakManualResetEvent osiągnąć ten poziom wydajności? ”.

EDYTOWAĆ: Ponieważ ktoś zapytał o funkcję, która kolejkuje pozycje, tutaj jest, wraz z pełnym systemem w tej chwili.

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);
            }
        }
    }
}

questionAnswers(2)

yourAnswerToTheQuestion