6

我是 LINQ 和 PLINQ 的新手,我正在构建一个项目来测试它们。

存根:

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

存根集合:

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

然后我有一些方法来迭代存根集合并计算有多少存根将布尔值设置为真:

前锋:

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

有用

林克:

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

它有效(比 foreach 慢一点)

普林克:

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,没有结果

为什么?唯一的区别是 AsParallel()

4

1 回答 1

6

问题出在您的 IEnumerator 实现中:

    public bool MoveNext()
    {
        index++;

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

我不确定为什么 PLINQ 会这样做,但即使到达集合的末尾,也会多次调用 MoveNext。问题是您的实现存在缺陷:在到达集合末尾后再次调用 MoveNext 时,索引将重置为 -1,因此枚举将重新开始。这就是为什么你陷入无限循环的原因。只需删除该index = -1行(并且可能重新考虑该方法以在到达枚举结束时停止增加索引)并且它会起作用。

于 2012-07-21T14:37:06.157 回答