首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >IEnumerable方法与AsParallel

IEnumerable方法与AsParallel
EN

Stack Overflow用户
提问于 2013-10-24 20:26:40
回答 1查看 529关注 0票数 2

我得到了以下扩展方法:

代码语言:javascript
复制
static class ExtensionMethods
{
    public static IEnumerable<IEnumerable<T>> Subsequencise<T>(
        this IEnumerable<T> input,
        int subsequenceLength)
    {
        var enumerator = input.GetEnumerator();
        SubsequenciseParameter parameter = new SubsequenciseParameter
            { 
                Next = enumerator.MoveNext()
            };

        while (parameter.Next)
                yield return getSubSequence(
                    enumerator,
                    subsequenceLength,
                    parameter);         
    }

    private static IEnumerable<T> getSubSequence<T>(
        IEnumerator<T> enumerator,
        int subsequenceLength,
        SubsequenciseParameter parameter)
    {
        do
        {
            lock (enumerator) // this lock makes it "work"
            {                 // removing this causes exceptions.
                if (parameter.Next)
                    yield return enumerator.Current;
            }

        } while ((parameter.Next = enumerator.MoveNext())
                  && --subsequenceLength > 0);
    }

    // Needed since you cant use out or ref in yield-return methods...
    class SubsequenciseParameter
    {
        public bool Next { get; set; }
    }
}

它的目的是将一个序列分割成给定大小的子序列。

这样称呼它:

代码语言:javascript
复制
foreach (var sub in "abcdefghijklmnopqrstuvwxyz"
                    .Subsequencise(3)
                    .**AsParallel**()
                    .Select(sub =>new String(sub.ToArray()))
{
    Console.WriteLine(sub);
}

Console.ReadKey();

工作,但是中间有一些空行,因为有些线程“太晚了”并输入了第一个收益率返回。

我试着在任何地方放置更多的锁,但是我无法将这个工作与as并行结合起来。

很明显,这个例子根本没有理由使用as并行。这只是为了演示如何调用该方法。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-10-24 20:45:27

问题是,使用迭代器是延迟计算的,所以您返回一个从多个线程中使用的延迟计算的迭代器。

您可以通过如下重写您的方法来修复这个问题:

代码语言:javascript
复制
public static IEnumerable<IEnumerable<T>> Subsequencise<T>(this IEnumerable<T> input, int subsequenceLength)
{
    var syncObj = new object();
    var enumerator = input.GetEnumerator();
    if (!enumerator.MoveNext())
    {
        yield break;
    }

    List<T> currentList = new List<T> { enumerator.Current };
    int length = 1;
    while (enumerator.MoveNext())
    {
        if (length == subsequenceLength)
        {
            length = 0;
            yield return currentList;
            currentList = new List<T>();                
        }
        currentList.Add(enumerator.Current);
        ++length;
    }
    yield return currentList;
}

这将执行相同的函数,但不使用迭代器来实现“嵌套”IEnumerable<T>,从而避免了这个问题。请注意,这也避免了锁定以及自定义SubsequenciseParameter类型。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19575966

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档