2010-04-29 38 views
8

Tôi mới đến luồng và muốn làm điều gì đó tương tự như câu hỏi này:Sử dụng đa luồng cho vòng lặp

Speed up loop using multithreading in C# (Question)

Tuy nhiên, tôi không chắc chắn nếu giải pháp đó là tốt nhất đối với tôi như tôi muốn họ tiếp tục chạy và không bao giờ kết thúc. (Tôi cũng đang sử dụng .net 3.5 chứ không phải 2.0 như đối với câu hỏi đó.)

tôi muốn làm một cái gì đó như thế này:

foreach (Agent agent in AgentList) 
{ 
    // I want to start a new thread for each of these 
    agent.DoProcessLoop(); 
} 

--- 

public void DoProcessLoop() 
{ 
    while (true) 
    { 
     // do the processing 

     // this is things like check folder for new files, update database 
     // if new files found 
    } 
} 

có một ThreadPool là giải pháp tốt nhất hoặc là có cái gì đó phù hợp với điều này tốt hơn?

Cập nhật: Cảm ơn tất cả các câu trả lời tuyệt vời! Tôi nghĩ tôi sẽ giải thích trường hợp sử dụng chi tiết hơn. Một số tác nhân có thể tải tệp lên một thư mục. Mỗi tác nhân có thư mục riêng của họ để họ có thể tải nội dung lên (tệp csv, hình ảnh, pdf). Dịch vụ của chúng tôi (nó có nghĩa là một dịch vụ windows chạy trên máy chủ họ tải tài sản của họ lên, yên tâm tôi sẽ quay trở lại với các câu hỏi về dịch vụ windows đôi khi sớm :)) sẽ tiếp tục kiểm tra thư mục của mỗi đại lý nếu có bất kỳ tài sản mới nào và nếu có, cơ sở dữ liệu sẽ được cập nhật và cho một số trang tĩnh được tạo. Có thể mất một lúc để họ tải lên mọi thứ và chúng tôi muốn họ có thể thấy các thay đổi được tải lên của họ khá nhiều ngay lập tức, chúng tôi nghĩ rằng một chuỗi cho mỗi tác nhân sẽ là một ý tưởng hay vì không có đại lý nào cần đợi người khác kết thúc (và chúng tôi có nhiều bộ xử lý nên muốn sử dụng toàn bộ dung lượng của chúng). Hy vọng điều này giải thích nó!

Cảm ơn,

Annelie

+0

Một chút của một tiếp tuyến, nhưng bạn có thể muốn cố gắng để làm cho các chủ đề hơn một chút sự kiện điều khiển hơn là chạy trong một vòng lặp chặt chẽ. Chạy trong một vòng lặp chặt chẽ như vậy có thể sẽ chỉ kết thúc búa xử lý của bạn và lãng phí tài nguyên, cũng như làm cho các chủ đề có công việc thực sự để làm chỉ ngồi xung quanh cho thời gian dài hơn. – Kitsune

+0

Chủ đề khác không nhất thiết phải là câu trả lời và có thể trở thành một vấn đề. Vì vậy, giả sử bạn có 20 tác nhân và sinh ra một chuỗi cho mỗi chủ đề. File i/o luôn luôn là một nút cổ chai, vì vậy bạn có 20 chủ đề liên tục bỏ phiếu cho hệ thống tập tin để thay đổi - đó sẽ là một tác động tiêu cực đến hiệu năng. Mỗi chủ đề này cũng sẽ sử dụng thời gian CPU cho việc bỏ phiếu đó, do đó, trên một hộp bốn nhân, mỗi lõi sẽ bị tấn công với năm trong số các chủ đề này (giả sử 20 tác nhân). các tệp mới) sẽ được hoán đổi để cho phép bỏ phiếu thực thi. – Ragoczy

Trả lời

12

Với việc sử dụng cụ thể mô tả của bạn (xem cho các tập tin), tôi muốn đề nghị bạn sử dụng một FileSystemWatcher để xác định khi có các tệp mới và sau đó kích hoạt một luồng với threadpool để xử lý các tệp cho đến khi không còn quá trình xử lý - tại thời điểm đó, chuỗi thoát.

Điều này sẽ giảm i/o (vì bạn không thường xuyên bỏ phiếu đĩa), giảm mức sử dụng CPU (vì vòng lặp liên tục của nhiều luồng bỏ phiếu sẽ sử dụng chu kỳ) và giảm số lượng chủ đề bạn đang chạy tại bất kỳ thời điểm nào (giả sử không có sửa đổi liên tục nào được thực hiện đối với hệ thống tệp).

Bạn có thể muốn mở và đọc các tệp chỉ trên chuỗi chính và chuyển dữ liệu đến chuỗi công việc (nếu có thể), để giới hạn i/o cho một chuỗi đơn lẻ.

+0

Vừa mới đăng bài này. –

+1

Chắc chắn là một cách tiếp cận tốt hơn. –

+0

Đây là phương pháp phù hợp. Trình xử lý sự kiện FileSystemWatcher của bạn sẽ đăng các tệp mới lên hàng đợi, được theo dõi bởi một chuỗi giám sát riêng biệt sinh ra các chuỗi công việc riêng biệt để nhập các tệp. Điều này cho phép bạn kiểm soát số lượng các luồng công nhân và giảm thiểu khả năng tràn bộ đệm FileSystemWatcher. Mỗi chuỗi công việc phải liên tục kiểm tra cho đến khi nó được độc quyền truy cập vào tệp của nó để bạn không bắt đầu đọc cho đến khi tác giả của tệp hoàn tất. –

2

Một vấn đề với ThreadPool sẽ là nếu hồ sẽ xảy ra là nhỏ hơn so với số đại lý mà bạn muốn có, những người bạn cố gắng để bắt đầu sau không bao giờ có thể thực hiện . Một số tác vụ có thể không bao giờ bắt đầu thực thi và bạn có thể bỏ đói mọi thứ khác trong miền ứng dụng của bạn sử dụng nhóm chủ đề. Bạn có lẽ tốt hơn không đi xuống con đường đó.

+0

@tehMick Điểm thú vị! Bạn có bất cứ gợi ý nào về việc phải làm gì thay thế không? Lý do chúng tôi muốn làm luồng là chúng tôi không muốn bất kỳ ai tải lên nội dung phải đợi quá lâu và khi chúng tôi có nhiều bộ xử lý thì chúng tôi sẽ sử dụng hết công suất của họ. – annelie

+0

Nếu bạn đang theo dõi một hệ thống tập tin, tôi chắc chắn sẽ làm điều đó trên một chủ đề duy nhất vì nhiều chủ đề sẽ chỉ chiến đấu trên truy cập tập tin. Sau đó, mỗi tệp bạn tìm thấy có thể được xếp hàng đợi dưới dạng mục công việc cho nhóm chủ đề để chọn. Nhưng có một số cách hợp lệ khác để tiếp cận nó. –

+0

Mặc dù, suy nghĩ về nó nhiều hơn, tôi có thể hiểu lầm trường hợp sử dụng ở đây, tôi không hoàn toàn rõ ràng về ngữ cảnh. –

-1

Cho đến khi bạn nâng cấp lên .NET 4, ThreadPool có thể là lựa chọn tốt nhất của bạn. Bạn cũng có thể muốn sử dụng Semaphore và AutoResetEvent để kiểm soát số lượng các chuỗi đồng thời. Nếu bạn đang nói về công việc lâu dài thì chi phí của việc khởi động và quản lý các luồng của riêng bạn là thấp và giải pháp thanh lịch hơn. Điều đó sẽ cho phép bạn sử dụng một WorkerThread.Join() để bạn có thể đảm bảo rằng tất cả các luồng công nhân được hoàn thành trước khi bạn tiếp tục thực hiện.

+0

Tôi giả sử thời gian (đúng) chỉ là psuedocode. –

1

Một nhóm chủ đề hữu ích khi bạn mong đợi các chuỗi được sắp xếp vào và ra khỏi sự tồn tại khá thường xuyên, không phải cho một số chuỗi được xác định trước.

+0

@Tejs Yep, tôi thấy quan điểm của bạn. Bất kỳ đề xuất cho những gì để làm thay vào đó?(xem bình luận trước đây của tôi về lý do chúng tôi đã đi cho điều này) – annelie

+0

Tôi sẽ không bao giờ thực hiện một vòng lặp (true) - đó là không thể thực hiện trừ khi bạn muốn ném một ngoại lệ, hoặc chỉ cần hủy bỏ các chủ đề. Nếu bạn cần phải có đồng thời, hãy xem xét chỉ cần làm một cái gì đó như thế này:

 Thread x = new Thread(new ThreadStart(Foo)); x.Start(); // If Some conditions change later, and you want to kill it, call x.Abort() public void Foo() { // Do Stuff } 
Tejs

2

Bạn chắc chắn không muốn sử dụng ThreadPool cho mục đích này. Chủ đề ThreadPool không có nghĩa là được sử dụng cho các tác vụ dài hạn ("vô hạn" được tính là dài hạn), vì điều đó rõ ràng sẽ ràng buộc các tài nguyên có nghĩa là được chia sẻ.

Đối với ứng dụng của bạn, nó có lẽ sẽ tốt hơn để tạo một thread (không từ ThreadPool) và trong chủ đề mà thực hiện while vòng lặp của bạn, bên trong đó bạn lặp qua bộ sưu tập đại lý của bạn và thực hiện các xử lý cho mỗi người . Trong vòng lặp while, bạn cũng nên sử dụng cuộc gọi Thread.Sleep để bạn không tối đa hóa bộ xử lý (có các cách thực thi mã theo định kỳ tốt hơn, nhưng Thread.Sleep sẽ hoạt động cho mục đích của bạn).

Cuối cùng, bạn cần bao gồm một số cách cho vòng lặp while để thoát khi chương trình của bạn chấm dứt.

Cập nhật: Cuối cùng, đa luồng thực hiện không tự động tăng tốc mã chạy chậm. Chín phụ nữ không thể sinh con trong một tháng.

+1

Nhưng một octo-mom có ​​thể làm cho một em bé mỗi tháng ... :-P –

+1

Mặc dù luồng thường làm tăng tốc độ xử lý thời gian, đặc biệt là trong nhiều- bộ xử lý lõi của máy tính để bàn và máy chủ hiện đại. Vì vậy, lâu là không có một tài nguyên duy nhất mà mỗi thread cần họ sẽ thực hiện nhanh hơn ngay cả trên một máy tính lõi đơn. Ngoài ra, ThreadPool có nghĩa là để được sử dụng! Tôi thực sự không nghĩ rằng họ có nghĩa là trong khi (true) khác hơn cho các mục đích của psudocode. –

+0

@Nate: OQ nói "Tôi muốn họ tiếp tục chạy và không bao giờ kết thúc", điều tôi đã nghĩ là họ có nghĩa là "trong khi (đúng)" khá đúng nghĩa đen. Tất nhiên ThreadPool là có nghĩa là để được sử dụng - chỉ cần không theo cách này. – MusiGenesis

0

Hmm .. như Ragoczy chỉ ra, tốt hơn là sử dụng FileSystemWatcher để theo dõi các tệp. Tuy nhiên, kể từ khi bạn có các hoạt động bổ sung, bạn có thể nghĩ về đa luồng.

Nhưng hãy cẩn thận, cho dù bạn có bao nhiêu người xử lý, có giới hạn về khả năng của nó. Bạn có thể không muốn tạo bao nhiêu chủ đề với số lượng người dùng đồng thời, vì lý do đơn giản là số lượng tác nhân của bạn có thể tăng lên.

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