2015-11-05 16 views
5

Tôi tin rằng một trường hợp khá phổ biến là có một hàng đợi các mục cần được xử lý N tại một thời điểm.Có lớp xếp hàng .NET cho phép xóa nhiều mục cùng lúc không?

Ví dụ .. nếu chúng ta có 23 items và cần xử lý 10 cùng một lúc, nó sẽ như thế nào:

Process batch of 10 
Process batch of 10 
Process batch of 3 

tôi có thể giải quyết vấn đề này trong một variaty cách khác nhau. Câu hỏi của tôi là: Khuôn khổ .NET có cung cấp bất kỳ lớp nào được thiết kế đặc biệt để giải quyết kịch bản này không? Lớp Queue sẽ hoàn hảo nhưng không cho phép khử nhiều mục cùng một lúc.

+2

Có thể bạn không chỉ dequeue 10 mục trong một vòng lặp và sau đó xử lý chúng? Tôi có thiếu một cái gì đó từ câu hỏi của bạn mà ngăn cản cách tiếp cận này? – xxbbcc

+1

tại sao bạn không enqueue hoàn thành lô 10? – Carsten

+0

Vâng .. Tôi không muốn làm điều đó nhưng thực sự không có nhiều lý do cho điều đó. Nó chỉ là xấu xí. Nhưng yeah .. Tôi có lẽ nên làm điều đó. –

Trả lời

10

Bạn có thể tạo ra một phương pháp mở rộng trên Queue<T>:

public static class QueueExtensions 
{ 
    public static IEnumerable<T> DequeueChunk<T>(this Queue<T> queue, int chunkSize) 
    { 
     for (int i = 0; i < chunkSize && queue.Count > 0; i++) 
     { 
      yield return queue.Dequeue(); 
     } 
    } 
} 

Cách sử dụng:

var q = new Queue<char>(); 
q.DequeueChunk(10) // first 10 items 
q.DequeueChunk(10) // next 10 items 

Ví dụ:https://dotnetfiddle.net/OTcIZX

+0

+1, Cảm ơn câu trả lời của bạn. Tôi tin rằng điều này là sạch nhất. Tôi chấp nhận một cái khác bởi vì tôi đã nói một cái gì đó được xây dựng trong (sự kiện mặc dù đó là một thư viện mở rộng) trong câu hỏi. Cảm ơn một lần nữa. –

+1

Chắc chắn-- chỉ cần nghĩ rằng tôi muốn thêm một triển khai trong trường hợp nó hữu ích cho bất cứ ai khác –

1

Thư viện lưu trữ TPL Dataflow cung cấp BatchBlock < T > nhóm các chuỗi thư đầu vào thành các đoạn có kích thước mong muốn.

var bb = new BatchBlock<int>(10); 
var ab = new ActionBlock<int[]>((Action<int[]>)chunk=>HandleChunk(chunk)); 

bb.LinkTo(ab, new DataflowLinkOptions(){PropogateCompletion = true}); 

for(int i = 0; i < 23; ++i) 
{ 
    bb.Post(i); 
} 

bb.Complete(); 
ab.Completion.Wait(); 
+0

cảm ơn câu trả lời. Chỉ vì vậy tôi rõ ràng: Bạn 'Đăng' vào một' BatchBlock' bạn đang chỉ định dữ liệu được xử lý. Nhưng chỉ có 10 sẽ được xử lý tại một thời điểm. Vì vậy, có lẽ, 'Post' sẽ chặn chuỗi chủ đề cho đến khi một số mục trả về. Đúng? Hoặc là nó song song? Nó có lẽ song song vì nó từ thư viện TPL –

+0

@andrerpena Điều đó là đúng. Theo mặc định, ActionBlock xử lý các thông điệp tuần tự. Bạn có thể thay đổi hành vi này bằng cách chỉ định MaxDegreeOfParalIelism trong các tùy chọn. – alexm

+0

Tôi hiểu. Cảm ơn. Vì vậy, tôi giả định rằng hành động 'chunk => HandleChunck (chunk)' sẽ được thực hiện cho mỗi 10 mục (đoạn sẽ là 10 mục). Tuy nhiên, làm thế nào nó biết nó nên xử lý 3 cuối cùng mặc dù chúng tôi đã không đạt đến 30? Có phải vì phương pháp Hoàn thành không? Quá trình sẽ bắt đầu chỉ khi Complete được gọi? –

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