Ngắt song song.foreach?


111

Làm cách nào để thoát khỏi vòng lặp song song.for?

Tôi có một câu lệnh khá phức tạp trông giống như sau:

Parallel.ForEach<ColorIndexHolder>(ColorIndex.AsEnumerable(),
    new Action<ColorIndexHolder>((ColorIndexHolder Element) =>
    {
        if (Element.StartIndex <= I && Element.StartIndex + Element.Length >= I)
        {
            Found = true;
            break;
        }
    }));

Sử dụng lớp song song, tôi có thể tối ưu hóa quá trình này cho đến nay. Tuy nhiên; Tôi không thể tìm ra cách phá vỡ vòng lặp song song? Câu break;lệnh ném ra lỗi cú pháp sau:

Không có vòng lặp nào để phá vỡ hoặc tiếp tục


1
Bạn có mong đợi rằng TẤT CẢ các trường hợp song song của vòng lặp ngắt cùng một lúc không?
n8wrl 24/09/12

Câu trả lời:


185

Sử dụng ParallelLoopState.Breakphương pháp:

 Parallel.ForEach(list,
    (i, state) =>
    {
       state.Break();
    });

Hoặc trong trường hợp của bạn:

Parallel.ForEach<ColorIndexHolder>(ColorIndex.AsEnumerable(),
    new Action<ColorIndexHolder, ParallelLoopState>((ColorIndexHolder Element, ParallelLoopState state) =>
    {
        if (Element.StartIndex <= I && Element.StartIndex + Element.Length >= I)
        {
            Found = true;
            state.Break();
        }
    }));

chính xác. đã chuẩn bị đăng bài này cho chính mình.
Mare Infinitus 24/09/12

1
Suy nghĩ về một vòng lặp foreach tuần tự, nó đảm bảo rằng các mục trước mục mà vì bất kỳ lý do gì gây ra lỗi sẽ được xử lý. Điều gì về một Parallel.ForEach trong đó thứ tự của các mục không nhất thiết phải là thứ tự mà chúng được xử lý? Nó có được đảm bảo rằng tất cả các mục trong IEnumerable <...> trước mục gọi trạng thái.Break () đang được xử lý và những mục đến sau nó thì không? Mặc dù cái trước có thể đạt được bằng cách nào đó, tôi không thấy cái sau sẽ có thể đạt được như thế nào.
Hendrik Wiese

4
@Hendrik Wiese: Tài liệu nói: Calling the Break method informs the for operation that iterations after the current one don't have to execute. However, all iterations before the current one will still have to be executed if they haven't already.there is no guarantee that iterations after the current one will definitely not execute.
Tudor

2
vì vậy, sau đó sẽ state.Stop()thích hợp hơn để đạt được kết quả mong đợi một cách đáng tin cậy, như được đề cập bên dưới bởi Mike Perrenoud và MB Bentley
xtreampb

44

Bạn thực hiện việc này bằng cách sử dụng quá tải của Parallel.Forhoặc Parallel.ForEachchuyển sang trạng thái vòng lặp, sau đó gọi ParallelLoopState.Breakhoặc ParallelLoopState.Stop. Sự khác biệt chính là ở mức độ nhanh chóng của mọi thứ - với Break(), vòng lặp sẽ xử lý tất cả các mục có "chỉ mục" sớm hơn hiện tại. Với Stop(), nó sẽ thoát ra càng nhanh càng tốt.

Để biết chi tiết, hãy xem Cách thực hiện: Dừng hoặc Ngắt từ một song song .


3
+1, có vẻ như một vài người trong chúng ta ở đây có cùng câu trả lời :) - ồ và tôi đã nhận được sự ủng hộ của bạn về người đàn ông bình luận khác đó.
Mike Perrenoud

Cảm ơn vì lời giải thích này. Bạn có biết khi nào ngắt hoặc dừng được gọi, đó là trường hợp các lần lặp đang thực hiện đã hoàn thành hay nó dừng các lần lặp giữa chừng khi thực hiện?
CeejeeB

1
@CeejeeB Các hoạt động đang thực thi hiện đã hoàn tất.
Reed Copsey

12

Những gì bạn nên sử dụng là Any, thay vì một vòng lặp foreach:

bool Found = ColorIndex.AsEnumerable().AsParallel()
    .Any(Element => Element.StartIndex <= I 
      && Element.StartIndex + Element.Length >= I);

Any đủ thông minh để dừng lại ngay khi biết rằng kết quả đó phải là sự thật.


10

LoopState chắc chắn là một câu trả lời tuyệt vời. Tôi thấy các câu trả lời trước có quá nhiều thứ khác nên rất khó để xem câu trả lời, vì vậy đây là một trường hợp đơn giản:

using System.Threading.Tasks;

Parallel.ForEach(SomeTable.Rows(), (row, loopState) =>
{
    if (row.Value == testValue)
    {
        loopState.Stop();  // Stop the ForEach!
    }       
    // else do some other stuff here.
});

5

Chỉ cần sử dụng những loopStategì có thể được cung cấp.

Parallel.ForEach<ColorIndexHolder>(ColorIndex.AsEnumerable(),  
    new Action<ColorIndexHolder>((Element, loopState) => { 
        if (Element.StartIndex <= I && Element.StartIndex + Element.Length >= I) { 
            loopState.Stop();
        }     
})); 

Hãy xem bài viết MSDN này để làm ví dụ.

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.