Application freezes using PLINQ AsParallel (). No problem with LINQ

I am new to LINQ and PLINQ, and I am building a project to test them.

Stub:

class Stub { private Boolean mytf; public Stub() { Random generator = new Random(); if (generator.NextDouble() < 0.5) { mytf = false; } else mytf = true; } public Boolean tf { get { return mytf; } } } 

StubCollection:

 class StubCollection : IEnumerable { Stub[] stubs; public StubCollection(int n) { stubs = new Stub[n]; for (int i = 0; i < n; i++) { stubs[i] = new Stub(); } } IEnumerator IEnumerable.GetEnumerator() { return new StubIterator(this); } public class StubIterator : IEnumerator { private StubCollection sc; private int index = -1; public StubIterator(StubCollection _sc) { sc = _sc; } public bool MoveNext() { index++; if (index < sc.stubs.Length) { return true; } else { index = -1; return false; } } public object Current { get { if (index <= -1) { throw new InvalidOperationException(); } return sc.stubs[index]; } } public void Reset() { index = -1; } } } 

then I have some methods for iterating over stubcollection and counting how many stubs boolean has for true:

Eogeasp:

 Stopwatch sw = new Stopwatch(); Int32 n = 0; sw.Start(); foreach (Stub s in sc) if (s.tf) n++; sw.Stop(); MessageBox.Show("n:" + n.ToString() + " timer:" + sw.ElapsedMilliseconds.ToString()); 

works

LINQ:

 Stopwatch sw = new Stopwatch(); Int32 n = 0; sw.Start(); var trueStubs = from Stub s in sc where s.tf select s; n = trueStubs.Count(); sw.Stop(); MessageBox.Show("n:" + n.ToString() + " timer:" + sw.ElapsedMilliseconds.ToString()); 

it works (a bit slower than foreach)

PLINQ:

 Stopwatch sw = new Stopwatch(); Int32 n = 0; sw.Start(); var trueStubs = from Stub s in sc.AsParallel() where s.tf select s; n = trueStubs.Count(); sw.Stop(); MessageBox.Show("n:" + n.ToString() + " timer:" + sw.ElapsedMilliseconds.ToString()); 

100% processor, no result

why? the only difference is that AsParallel ()

+6
source share
1 answer

The problem is implementing IEnumerator:

  public bool MoveNext() { index++; if (index < sc.stubs.Length) { return true; } else { index = -1; return false; } } 

I'm not quite sure why PLINQ does this, but MoveNext is called several times, even when the end of the collection is reached. The problem is that your implementation is wrong: when you call MoveNext again after reaching the collection, the index will be reset to -1, so the enumeration will begin. That is why you are stuck in an endless loop. Just delete the line index = -1 (and maybe rethink the method a bit to stop the incremental index when the end of the enumeration is reached) and it will work.

+6
source

Source: https://habr.com/ru/post/921028/


All Articles