Làm cách nào tôi có thể giới hạn Parallel.ForEach?


295

Tôi có một vòng lặp async Parallel.ForEach () mà tôi tải xuống một số trang web. Băng thông của tôi bị giới hạn nên tôi chỉ có thể tải xuống x trang mỗi lần nhưng Parallel.ForEach thực thi toàn bộ danh sách các trang web mong muốn.

Có cách nào để giới hạn số luồng hoặc bất kỳ bộ giới hạn nào khác trong khi chạy Parallel.ForEach không?

Mã trình diễn:

Parallel.ForEach(listOfWebpages, webpage => {
  Download(webpage);
});

Nhiệm vụ thực tế không liên quan gì đến các trang web, vì vậy các giải pháp thu thập dữ liệu web sáng tạo sẽ không giúp ích.


@jKlaus Nếu danh sách không được sửa đổi, ví dụ như đó chỉ là một bộ URL, tôi thực sự không thể nhìn thấy vấn đề?
Shiv

@Shiv, cho đủ thời gian bạn sẽ ... Đếm số lần thực hiện của bạn và so sánh nó với số lượng của danh sách.
jKlaus

@jKlaus Bạn đang nói gì sẽ đi sai?
Shiv

1
@jKlaus bạn đang sửa đổi một phần tử không phải là chủ đề (số nguyên). Tôi hy vọng nó sẽ không hoạt động trong kịch bản đó. Mặt khác, OP không sửa đổi bất cứ thứ gì cần phải an toàn.
Shiv

2
@jKlaus Đây là một ví dụ về Parallel.ForEach đặt số đếm chính xác> dotnetfiddle.net/moqP2C . Liên kết MSDN: msdn.microsoft.com/en-us/l
Library / dd997393 (v = vs.110) .aspx

Câu trả lời:


564

Bạn có thể chỉ định một MaxDegreeOfParallelismtrong một ParallelOptionstham số:

Parallel.ForEach(
    listOfWebpages,
    new ParallelOptions { MaxDegreeOfParallelism = 4 },
    webpage => { Download(webpage); }
);

MSDN: Parallel.ForEach

MSDN: ParallelOptions.MaxDegreeOfParallelism


59
Nó có thể không áp dụng cho trường hợp cụ thể này nhưng tôi đoán rằng tôi sẽ ném nó đi trong trường hợp có ai thắc mắc về điều này và thấy nó hữu ích. Ở đây tôi đang sử dụng 75% (làm tròn) số lượng bộ xử lý. var opts = new ParallelOptions { MaxDegreeOfParallelism = Convert.ToInt32(Math.Ceiling((Environment.ProcessorCount * 0.75) * 1.0)) };
jKlaus

4
Chỉ để cứu bất kỳ ai khác phải tra cứu nó trong tài liệu, việc chuyển một giá trị -1cũng giống như không chỉ định nó: "Nếu [giá trị] là -1, thì không có giới hạn về số lượng hoạt động đồng thời"
stuartd

Theo tài liệu của tôi thì không rõ ràng - việc đặt MaxDegreeOfParallelism thành 4 (chẳng hạn) có nghĩa là sẽ có 4 luồng mỗi lần chạy 1/4 vòng lặp (một vòng gồm 4 luồng được gửi đi) hoặc mỗi luồng vẫn thực hiện một vòng lặp lặp đi lặp lại và chúng ta chỉ giới hạn có bao nhiêu chạy song song?
Hashman

7
Để rõ ràng lõi và chủ đề không phải là điều tương tự. Tùy thuộc vào CPU, có một số luồng khác nhau cho mỗi lõi, thường là 2 cho mỗi lõi. Ví dụ: nếu bạn có CPU 4 lõi với 2 luồng trên mỗi lõi, thì bạn có tối đa 8 luồng. Để điều chỉnh bình luận @jKlaus var opts = new ParallelOptions { MaxDegreeOfParallelism = Convert.ToInt32(Math.Ceiling((Environment.ProcessorCount * 0.75) * 2.0)) };. Liên kết với các chủ đề so với lõi - Askubfox.com/questions/668538/ trên
TheMiddleMan

41

Bạn có thể sử dụng ParallelOptions và đặt MaxDegreeOfParallelism để giới hạn số lượng luồng đồng thời:

Parallel.ForEach(
    listOfwebpages, 
    new ParallelOptions{MaxDegreeOfParallelism=2}, 
    webpage => {Download(webpage);});     

21

Sử dụng một tình trạng quá tải khác Parallel.Foreachcần một ParallelOptionsthể hiện và đặt MaxDegreeOfParallelismđể giới hạn số lượng thực thi song song.


11

Và đối với người dùng VB.net (cú pháp rất lạ và khó tìm) ...

Parallel.ForEach(listOfWebpages, New ParallelOptions() With {.MaxDegreeOfParallelism = 8}, Sub(webpage)
......end sub)  
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.