2011-08-23 22 views
8

Tôi đang phát triển một ứng dụng dạng cửa sổ (C#), và trong khi chương trình đang chạy, nó tạo ra đối tượng thêm chúng vào một danh sách. Tôi phải xử lý các mục trong danh sách, với FIFO (đầu tiên trong lần đầu tiên ra). Tôi muốn làm điều này trong một backgroundthread và tôi phải xử lý chúng theo thứ tự, số 1, số 2, số 3 và như vậy. Và ngay sau khi một mục được thêm vào danh sách tôi muốn xử lý nó. Vì vậy, tôi phải có một cái gì đó để kiểm tra danh sách đó.BlockingCollection hoặc Queue <T> cho công việc?

cách tốt nhất để đạt được điều này là gì?

Tôi biết rằng blockingcollection làm điều gì đó tương tự, rằng nó chờ đợi cho một mục được bổ sung trước khi xử lý nó.

tôi có thể sử dụng một chủ đề duy nhất với Queue và chỉ while (true) và đưa mặt hàng nếu có bất kỳ?

Bạn nghĩ gì?

Trả lời

14

Âm thanh như bạn nên đi cho các BlockingCollection<T> nếu bạn đang lập kế hoạch về việc sử dụng một sợi nền. Bạn có thể dễ dàng thực hiện cùng một logic while(true) mà bạn đang tìm kiếm.

Các BlockingCollection<T> cung cấp cho bạn hai tính năng quan trọng

  1. Đó là thread-safe

  2. Khi bạn gọi Take(), nó sẽ chặn (tức là đợi cho đến khi có điều gì đó trong hàng đợi) cho bạn, vì vậy bạn không phải viết bất kỳ mã nào với ManualResetEvents và các loại tương tự, đây là một sự đơn giản hóa tốt đẹp.

+0

Có chính xác! Tôi chỉ yêu cầu điều này để xác nhận suy nghĩ của tôi và nếu ai đó có ý tưởng tốt hơn :) – syncis

+2

@ Jonathan Beerhalter: Hoặc, thay vì gọi 'Take', anh ta chỉ có thể làm chủ đề của mình làm một' foreach' trên ['GetConsumingEnumerable'] (http://msdn.microsoft.com/en-us/library/dd287186.aspx), sẽ cung cấp các mục khi chúng được đặt trong 'BlockingCollection '. – casperOne

+0

@syncis: 'GetConsumingEnumerable' sẽ chặn cho đến khi một mục được thêm vào' BlockingCollection 'giống như' Take' sẽ; vấn đề là, chủ đề nền của bạn làm gì khác ngoài việc xử lý các mục này? Nếu bạn đang cố gắng lưu chủ đề; không, bạn về cơ bản viết lại hồ bơi chủ đề và đó không phải là một ý tưởng hay. Lưu ý, nhiều mục hơn có thể xuất hiện cho 'Take' hoặc được sinh ra thông qua' GetConsumingEnumerable' trong khi bạn đang xử lý các mục của bạn từng cái một (hoặc bạn có thể gửi những mục đó được xử lý trong các chủ đề khác, tùy theo nhu cầu của bạn). – casperOne

0

NẾU bạn muốn chặn nếu hàng đợi rỗng sau đó sử dụng BlockingCollection - đó là lý tưởng ... NẾU bạn muốn nó nhiều hơn Queue-like (quyết định cho mình làm thế nào để đối phó với một trống) sau đó ConcurrentQueue.

Cả hai đều an toàn theo chủ đề, trong ConcurrentQueue hầu hết các hoạt động được triển khai không có khóa quá nhanh ... hoặc sử dụng trực tiếp hoặc làm kiểu cơ sở cho BlockingCollection của bạn ví dụ BlockingCollection<string> = new BlockingCollection<string> (new ConcurrentQueue<string>) - thậm chí bạn có thể đặt giới hạn tối đa trên đó (tham số thứ hai tùy chọn của hàm tạo).

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