我得到了以下扩展方法:
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; }
}
}它的目的是将一个序列分割成给定大小的子序列。
这样称呼它:
foreach (var sub in "abcdefghijklmnopqrstuvwxyz"
.Subsequencise(3)
.**AsParallel**()
.Select(sub =>new String(sub.ToArray()))
{
Console.WriteLine(sub);
}
Console.ReadKey();工作,但是中间有一些空行,因为有些线程“太晚了”并输入了第一个收益率返回。
我试着在任何地方放置更多的锁,但是我无法将这个工作与as并行结合起来。
很明显,这个例子根本没有理由使用as并行。这只是为了演示如何调用该方法。
发布于 2013-10-24 20:45:27
问题是,使用迭代器是延迟计算的,所以您返回一个从多个线程中使用的延迟计算的迭代器。
您可以通过如下重写您的方法来修复这个问题:
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类型。
https://stackoverflow.com/questions/19575966
复制相似问题