2012-02-24 22 views
5

Tôi đã sử dụng lại danh sách người tiêu dùng sản xuất ví dụ từ C# trong cuốn sách Nutshell của Albahari (http://www.albahari.com/threading/part5.aspx#_BlockingCollectionT) và một đồng nghiệp đã nhận xét: "Tại sao không được gọi là trên BlockingCollection trong việc vứt bỏ của bộ sưu tập? "Gọi Dispose trên một BlockingCollection <T>

Tôi không thể tìm thấy câu trả lời và lý do duy nhất tôi có thể đưa ra là việc thực hiện khối lượng công việc còn lại của hàng đợi sẽ không được xử lý. Tuy nhiên, khi tôi xử lý hàng đợi, tại sao nó sẽ không ngừng xử lý?

Bên cạnh "Tại sao bạn không nên vứt bỏ BlockingCollection?" Tôi cũng có một câu hỏi thứ hai "Liệu nó có hại nếu bạn không vứt bỏ một BlockingCollection?". Tôi cho rằng khi bạn đang sinh sản/xử lý nhiều hàng đợi của người tiêu dùng sản xuất, nó sẽ gây ra các vấn đề (không phải tôi muốn điều đó mà chỉ vì nguyên nhân của việc biết). Theo What does BlockingCollection.Dispose actually do? BlockingCollection chứa hai tay cầm chờ đợi (hiển nhiên) nên không gọi Dispose sẽ cho bạn một số vấn đề. Cảm ơn ken2k đã chỉ ra điều này.

Mã Tôi đang nói về:

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

Có thể liên quan: http://stackoverflow.com/questions/3188601/what-does-blockingcollection-dispose-actually-do – ken2k

+0

Tôi gặp sự cố với việc hủy bỏ việc thu thập chặn (ví dụ: giải phóng thời gian Take last), cho đến khi tôi bắt đầu sử dụng CancellationToken, xem https://stackoverflow.com/a/5759866/1544054 – Aviko

Trả lời

7

Bởi vì đó sẽ là một lỗi. Bộ sưu tập không thể được xử lý cho đến khi tất cả các chủ đề của người tiêu dùng đã thoát. Nếu đó không phải là interlocked thì những chủ đề sẽ bom với một ngoại lệ. Lớp học không theo bất kỳ cách nào có nhận thức về những gì người tiêu dùng đề có thể được kéo từ bộ sưu tập để nó không thể biết hợp lý khi nó là an toàn để xử lý. Tất cả những gì nó có thể làm là ngăn chặn thêm bất kỳ đối tượng nào do nhà sản xuất thêm vào, điều đó là hợp lý.

Đây là vấn đề thường gặp với các chủ đề, xử lý an toàn yêu cầu phải biết khi nào sợi hoàn tất. Mà thường đánh bại các điểm của việc sử dụng các chủ đề ở nơi đầu tiên, bạn không muốn chờ đợi cho đến khi một sợi kết thúc. Điều này dễ thấy nhất trong chính lớp Thread, nó tiêu thụ năm xử lý hệ điều hành gốc nhưng không có phương thức Dispose(). Họ cần phải được phát hành bởi finalizer. Tương tự ở đây.

Các vấn đề liên quan