I'm new to LINQ and PLINQ, and I'm 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 to iterate the stubcollection and count how many stubs have the boolean set to true:
foreach:
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());
it 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 (little 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% CPU, no result
why? the only difference is the AsParallel()
The problem is in your IEnumerator implementation:
public bool MoveNext()
{
index++;
if (index < sc.stubs.Length)
{
return true;
}
else
{
index = -1;
return false;
}
}
I'm not exactly sure why PLINQ does this, but MoveNext is called multiple times even when the end of the collection is reached. The problem is that your implementation is flawed: when calling MoveNext again after reaching the end of the collection, index will be reset to -1, so the enumeration will start over. That's why you're stuck in an endless loop. Just remove the index = -1
line (and maybe rethink the method a little to stop incrementing index when the end of the enumeration is reached) and it'll work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With