Re: Thread-safe specialized queue
От: desco США http://v2matveev.blogspot.com
Дата: 01.07.09 21:17
Оценка: 11 (2)
Здравствуйте, Пельмешко, Вы писали:

стремный сценарий:
1. Поток 1 делает Enqueue
2. Поток 2 (из пула), начавщий выполнять метод SenderJob проходит проверку в while и доходит до места А, не войдя в lock.

            while (this.msgQueue.Count > 0
              && !this.senderPaused)
            {
                string message;
                // A 
                lock (this.queueSync)
                {
                    message = this.msgQueue.Dequeue();
                }

                RaiseReceived(message);
                Thread.Sleep(this.timeout);
            }


3. Поток 1 последовательно вызывает Pause и Resume. В итоге посредством магических пассов (выделенный код) в пуле появляется еще один поток (3), выполняющий SenderJob.

        // Возобновление отправок
        public void Resume()
        {
            if (!this.senderPaused) return;

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

                if (this.msgQueue.Count > 0)
                {

                    // все проверки выполняются, попадаем сюда
                    this.senderAlive = true;
                    ThreadPool.QueueUserWorkItem(SenderJob);
                }
            }
        }


4. Поток 3 успешно проходит метод SenderJob, вытащив из очереди единственный элемент.
5. Просыпается поток 2, заходит под lock ... и успешно обламывается на попытке извлечь элемент из уже пустой очереди. Вуаля.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.