2011-11-17 25 views
8

Tôi có một bảng dữ liệu đầy đủ các mục tóm tắt và phần mềm của tôi cần phải trải qua và tiếp cận với dịch vụ web để lấy chi tiết, sau đó ghi lại các chi tiết đó về cơ sở dữ liệu. Lặp qua bảng một cách đồng bộ trong khi gọi dịch vụ web và chờ phản hồi quá chậm (có hàng nghìn mục nhập) vì vậy tôi muốn lấy kết quả (10 lần hoặc nhiều hơn một lúc) và chuỗi nó ra để nó thực hiện 10 hoạt động cùng một lúc.Cách tốt nhất để quản lý nhóm chủ đề chống lại hàng đợi cơ sở dữ liệu

Trải nghiệm của tôi với chuỗi C# được giới hạn để nói ít nhất, vậy cách tiếp cận tốt nhất là gì? NET có một số loại hệ thống hàng đợi threadsafe mà tôi có thể sử dụng để đảm bảo rằng các kết quả được xử lý đúng cách và theo thứ tự?

+2

Bạn đang sử dụng phiên bản .Net nào? Có những cải tiến lớn trong lập trình đa luồng trong .Net 4. – svick

+0

Nên có bao gồm rằng .. Hiện đang nhắm mục tiêu 3,5 nhưng tôi có thể đi 4,0 mà không gặp nhiều rắc rối. –

Trả lời

5

Tùy thuộc vào phiên bản .NET Framework bạn có hai tùy chọn khá tốt.

Bạn có thể sử dụng ThreadPool.QueueUserWorkItem trong mọi phiên bản.

int pending = table.Rows.Count; 
var finished = new ManualResetEvent(false); 
foreach (DataRow row in table.Rows) 
{ 
    DataRow capture = row; // Required to close over the loop variable correctly. 
    ThreadPool.QueueUserWorkItem(
    (state) => 
    { 
     try 
     { 
     ProcessDataRow(capture); 
     } 
     finally 
     { 
     if (Interlocked.Decrement(ref pending) == 0) 
     { 
      finished.Set(); // Signal completion of all work items. 
     } 
     } 
    }, null); 
} 
finished.WaitOne(); // Wait for all work items to complete. 

Nếu bạn đang sử dụng .NET Framework 4.0, bạn có thể sử dụng Task Parallel Library.

var tasks = new List<Task>(); 
foreach (DataRow row in table.Rows) 
{ 
    DataRow capture = row; // Required to close over the loop variable correctly. 
    tasks.Add(
    Task.Factory.StartNew(
    () => 
     { 
     ProcessDataRow(capture);   
     })); 
} 
Task.WaitAll(tasks.ToArray()); // Wait for all work items to complete. 

Có nhiều cách hợp lý khác để thực hiện việc này. Tôi làm nổi bật các mẫu ở trên vì chúng dễ dàng và hoạt động tốt. Trong trường hợp không có chi tiết cụ thể tôi không thể nói chắc chắn rằng một trong hai sẽ là một trận đấu hoàn hảo cho tình hình của bạn, nhưng họ phải là một điểm khởi đầu tốt.

Cập nhật:

Tôi đã có một thời gian ngắn hoạt động não xoàng xĩnh. Nếu bạn có sẵn TPL, bạn cũng có thể sử dụng Parallel.ForEach làm phương pháp đơn giản hơn tất cả các loại Task hocus-pocus mà tôi đã đề cập ở trên.

Parallel.ForEach(table.Rows, 
    (DataRow row) => 
    { 
    ProcessDataRow(row); 
    }); 
+0

Nhân tiện, bạn thực sự có thể sử dụng TPL trong 3.5 nếu bạn tải xuống phần mở rộng Phản hồi mở rộng từ trang web của Microsoft. –

+0

Công cụ tuyệt vời - cảm ơn mọi người. Có vẻ như có nhiều cách để làm da mèo này! –

+0

Chỉ một điều (và tôi biết, tôi sẽ đi RTFM!), Nhưng quy mô này như thế nào? Tôi sẽ làm hàng ngàn hàng này và tôi chắc chắn không muốn bắt đầu hàng ngàn chủ đề đồng thời. Tôi giả sử (hy vọng?) có một số loại giới hạn được tích hợp để điều này không làm máy tính của người dùng dừng lại. –

5

.NET có một số loại hệ thống xếp hàng luồng an toàn mà tôi có thể sử dụng để đảm bảo kết quả được xử lý đúng cách và theo thứ tự không?

Đây là thứ được thêm vào trong .NET 4. Lớp BlockingCollection<T>, theo mặc định, đóng vai trò là hàng đợi an toàn cho các nhà sản xuất/kịch bản người tiêu dùng.

Nó làm cho nó khá dễ dàng để tạo ra một số yếu tố "tiêu thụ" từ bộ sưu tập và quá trình, với một hoặc nhiều yếu tố thêm vào bộ sưu tập.

+0

Rất đẹp, tôi chắc chắn sẽ kiểm tra. Cảm ơn! –

+0

Còn hàng đợi đồng thời thì sao? http://msdn.microsoft.com/en-us/library/dd267265.aspx? – Dykam

+0

@Dykam 'BlockingCollection ', theo mặc định, kết thúc một 'ConcurrentQueue '. Trong khi bạn có thể sử dụng CQ trực tiếp, nếu bạn muốn làm việc trong kịch bản của nhà sản xuất/người tiêu dùng, như được mô tả, BC làm cho việc này đơn giản hơn một chút. –

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