2012-02-24 6 views
5

Я повторно очередь потребительского примера производителя из C# в ореховой скорлупе книги Albahari (http://www.albahari.com/threading/part5.aspx#_BlockingCollectionT) и его коллега заметил: «Почему не Dispose призвал BlockingCollection в Dispose из коллекции? "Вызов Dispose на BlockingCollection <T>

Я не смог найти ответ, и единственная причина, по которой я могу придумать, - это то, что выполнение оставшейся рабочей нагрузки очереди не будет обработано. Однако, когда я удаляю очередь, почему бы не остановить ее обработку?

Кроме того, «Почему вы не должны уничтожать BlockingCollection?» У меня также есть второй вопрос: «Разве это вредно, если вы не уничтожаете BlockingCollection?». Я полагаю, что когда вы создаете или удаляете много очередей потребителей-производителей, это создает проблемы (не то, что я хочу этого, а только для того, чтобы узнать). Согласно What does BlockingCollection.Dispose actually do? BlockingCollection содержит два дескриптора ожидания (очевидно), поэтому не вызывая Dispose, вы получите некоторые проблемы. Спасибо ken2k за это.

код Я говорю:

public class PCQueue : IDisposable 
{ 
    BlockingCollection<Action> _taskQ = new BlockingCollection<Action>(); 
    public PCQueue (int workerCount) 
    { 
    // Create and start a separate Task for each consumer: 
    for (int i = 0; i < workerCount; i++) 
     Task.Factory.StartNew (Consume); 
    } 

    public void Dispose() { _taskQ.CompleteAdding(); } 

    public void EnqueueTask (Action action) { _taskQ.Add (action); } 

    void Consume() 
    { 
    // This sequence that we’re enumerating will block when no elements 
    // are available and will end when CompleteAdding is called. 
    foreach (Action action in _taskQ.GetConsumingEnumerable()) 
     action();  // Perform task. 
    } 
} 
+2

Возможно, связанный: http://stackoverflow.com/questions/3188601/what-does-blockingcollection-dispose-actually-do – ken2k

+0

У меня возникли проблемы с сборкой блокировки (например, отпустите Take Take в последний раз), пока я не начал используйте CancellationToken, см. https://stackoverflow.com/a/5759866/1544054 – Aviko

ответ

7

Потому что это было бы ошибкой. Сбор не может быть удален до тех пор, пока все потребительские потоки не выйдут. Если это не блокируется, то эти потоки будут бомбить с исключением. Класс никоим образом не осознает, какие потребительские потоки могут вытаскивать из коллекции, поэтому он не может разумно знать, когда это безопасно распоряжаться. Все, что он может сделать, это предотвратить добавление каких-либо объектов производителем, это разумно.

Это обычная проблема с потоками, безопасное удаление требует знания, когда поток завершен. Что часто поражает точку использования потоков в первую очередь, вы не хотите ждать окончания потока. Это наиболее заметно в самом классе Thread, оно потребляет пять собственных дескрипторов операционной системы, но не имеет метода Dispose(). Они должны быть выпущены финализатором. Тоже самое.

 Смежные вопросы

  • Нет связанных вопросов^_^