Paralel.foreach?


111

Bir parallel.for döngüsünden nasıl çıkabilirim?

Aşağıdakine benzeyen oldukça karmaşık bir ifadem var:

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

Paralel sınıf kullanarak bu süreci açık ara optimize edebilirim. Ancak; Paralel döngüyü nasıl kıracağımı çözemiyorum? break;Açıklamada şu sözdizimi hatası atar:

Kırılacak veya devam edecek çevreleyici döngü yok


1
Döngünün TÜM paralel örneklerinin aynı anda kopmasını bekler miydiniz?
n8wrl

Yanıtlar:


185

ParallelLoopState.BreakYöntemi kullanın :

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

Veya sizin durumunuzda:

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();
        }
    }));

kesinlikle. bunu kendim göndermek üzereydim.
Mare Infinitus

1
Ardışık bir foreach döngüsü düşünüldüğünde, kırılmaya neden olan sebep ne olursa olsun, öğeden önceki öğelerin işleneceği garanti edilir. Parallel.ForEach'e ne dersiniz? Öğelerin sırasının mutlaka işlendikleri sıra olması gerekmez? Bir IEnumerable <...> içindeki state.Break () çağrısından önceki tüm öğelerin işlendiği ve ondan sonra gelen öğelerin işlenmediği de garanti ediliyor mu? Birincisi bir şekilde başarılabilse de, ikincisinin nasıl mümkün olacağını hiç anlamıyorum.
Hendrik Wiese

4
@Hendrik Wiese: Dokümanlar diyor ki: 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.vethere is no guarantee that iterations after the current one will definitely not execute.
Tudor

2
bu nedenle state.Stop(), aşağıda Mike Perrenoud ve MBentley tarafından belirtildiği gibi, beklenen sonuçları güvenilir bir şekilde elde etmek daha uygun olacaktır
xtreampb

44

Sen aşırı kullanarak arayarak bunu Parallel.Forya Parallel.ForEachbir döngü halinde geçtiği, daha sonra arayarak ParallelLoopState.Breakya ParallelLoopState.Stop. Temel fark, işlerin ne kadar hızlı kırılacağıdır - Break()döngü, mevcut olandan daha erken bir "indeksi" olan tüm öğeleri işler. İle Stop()olabildiğince çabuk çıkacaktır.

Ayrıntılar için bkz.Nasıl Yapılır: Bir Parallel.For Döngüsünden Durdurma veya Kopma .


3
+1, görünüşe göre buradaki birkaçımız tam olarak aynı cevaba sahip :) - oh ve ben de o diğer yoruma destek veriyorum adamım.
Mike Perrenoud

Bu açıklama için teşekkürler. Break veya stop'un ne zaman çağrıldığını biliyor musunuz, şu anda yürütülmekte olan yinelemelerin tamamlandığı veya yinelemeleri yürütmenin ortasında durdurduğu bir durum mu?
CeejeeB

1
@CeejeeB Şu anda yürütülen işlemler tamamlandı.
Reed Copsey

12

AnyBir foreach döngüsü yerine kullanmanız gereken şey :

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

Any sonucun doğru olması gerektiğini bildiği anda duracak kadar akıllıdır.


10

LoopState kesinlikle harika bir cevap. Önceki cevaplarda o kadar çok şey olduğunu buldum ki cevabı görmek zordu, işte basit bir durum:

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

Sadece loopStatesağlanabilecek olanı kullanın .

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

Örnek için bu MSDN makalesine bakın .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.