Re[2]: Thread-safe specialized queue
От: Пельмешко Россия blog
Дата: 02.07.09 04:35
Оценка:
Здравствуйте, desco, Вы писали:

D>стремный сценарий:

D>1. Поток 1 делает Enqueue
D>2. Поток 2 (из пула), начавщий выполнять метод SenderJob проходит проверку в while и доходит до места А, не войдя в lock.
D>3. Поток 1 последовательно вызывает Pause и Resume. В итоге посредством магических пассов (выделенный код) в пуле появляется еще один поток (3), выполняющий SenderJob.
D>4. Поток 3 успешно проходит метод SenderJob, вытащив из очереди единственный элемент.
D>5. Просыпается поток 2, заходит под lock ... и успешно обламывается на попытке извлечь элемент из уже пустой очереди. Вуаля.

Спасибо! Вчера голову сломал во время поиска подобного
Я так понимаю это вылечится одной дополнительной проверкой:

public void Resume()
{
    if (!this.senderPaused) return;

    lock(this.queueSync)
    {
        this.senderPaused = false;

        if (this.msgQueue.Count > 0 && !this.senderAlive)
        {
            this.senderAlive = true;
            ThreadPool.QueueUserWorkItem(SenderJob);
        }
    }
}

U>Для этого можно использовать AutoResetEvent, вызывая WaitOne для усыпления и Set() для пробуждения потока.
А ивентами не сильно дороже это будет? Объект ядра как-никак...

U>Также можешь глянуть http://files.rsdn.ru/12051/TaskPulling.rar класс LabeledThread, там решалась задача принципиально схожая с твоей.

Спасибо, поглядимс.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.