Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# IEnumerable元素的并行调用_C#_.net_Linq_Asynchronous_Parallel Processing - Fatal编程技术网

C# IEnumerable元素的并行调用

C# IEnumerable元素的并行调用,c#,.net,linq,asynchronous,parallel-processing,C#,.net,Linq,Asynchronous,Parallel Processing,我有一个名为Batch的IEnumerable方法,其工作原理如下 var list = new List<int>() { 1, 2, 4, 8, 10, -4, 3 }; var batches = list.Batch(2); foreach(var batch in batches) Console.WriteLine(string.Join(",", batch)); 我遇到的问题是,我要优化如下内容 foreach(var batch in batches)

我有一个名为
Batch
IEnumerable
方法,其工作原理如下

var list = new List<int>() { 1, 2, 4, 8, 10, -4, 3 }; 
var batches = list.Batch(2); 
foreach(var batch in batches)
    Console.WriteLine(string.Join(",", batch));
我遇到的问题是,我要优化如下内容

foreach(var batch in batches)
    ExecuteBatch(batch);

(因为执行包是一个涉及IO的长时间运行的操作)

然后我注意到每个
批处理
都会出错,只有一个元素是
默认值(int)
。知道发生了什么事或者怎么解决吗

批次:

public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> source, int size)
{
    for(var mover = source.GetEnumerator(); ;)
    {
        if(!mover.MoveNext())
            yield break;
        yield return LimitMoves(mover, size);
    }
}
private static IEnumerable<T> LimitMoves<T>(IEnumerator<T> mover, int limit)
{
    do yield return mover.Current;
    while(--limit > 0 && mover.MoveNext());
}
公共静态IEnumerable批处理(此IEnumerable源,int-size)
{
对于(var mover=source.GetEnumerator();;)
{
如果(!mover.MoveNext())
屈服断裂;
收益率限制移动(移动器、大小);
}
}
私有静态IEnumerable LimitMoves(IEnumerator mover,int limit)
{
不产生回流。电流;
而(--limit>0&&mover.MoveNext());
}

如评论中所述,您的实际问题是批处理的实现

此代码:

for(var mover = source.GetEnumerator(); ;)
{
    if(!mover.MoveNext())
        yield break;
    yield return LimitMoves(mover, size);
}
Batch
具体化时,此代码将持续调用
MoveNext()
,直到可枚举项用尽为止
LimitMoves()
使用相同的迭代器,并被延迟调用。由于
Batch
会耗尽可枚举项,
LimitMoves()
将永远不会发出项。(实际上,它只会发出
default(T)
,因为它总是返回
mover.Current
,一旦枚举完成,它将成为
default(T)

这里是批处理的一个实现,它在具体化时(因此在并行时)可以工作

公共静态IEnumerable批处理(此IEnumerable源,int-size)
{
var mover=source.GetEnumerator();
var currentSet=新列表();
while(mover.MoveNext())
{
currentSet.Add(mover.Current);
如果(currentSet.Count>=大小)
{   
产生返回电流集;
currentSet=新列表();
}
}
如果(currentSet.Count>0)
产生返回电流集;
}

或者,您可以使用批处理实现中附带的-。你可以看到他们的实施

你能详细说明一下这个问题吗?你是说批处理方法不起作用吗?在这种情况下,向我们展示it@Rob添加了实现您的问题是
Batch
正在耗尽枚举器(它处于for循环中,并不断调用
MoveNext()
LimitMoves
有机会之前。实际的错误是由于使用
ToArray()
实现集合而引起的,与并行性无关。如果将原始代码更改为
var batches=list.Batch(2).ToList();
,您将看到相同的问题。
Action[] executions = batches.Select(batch => new Action(() => ExecuteBatch(batch))).ToArray();
var options = new ParallelOptions { MaxDegreeOfParallelism = 4 };
Parallel.Invoke(options, executions);
public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> source, int size)
{
    for(var mover = source.GetEnumerator(); ;)
    {
        if(!mover.MoveNext())
            yield break;
        yield return LimitMoves(mover, size);
    }
}
private static IEnumerable<T> LimitMoves<T>(IEnumerator<T> mover, int limit)
{
    do yield return mover.Current;
    while(--limit > 0 && mover.MoveNext());
}
for(var mover = source.GetEnumerator(); ;)
{
    if(!mover.MoveNext())
        yield break;
    yield return LimitMoves(mover, size);
}
public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> source, int size)
{
    var mover = source.GetEnumerator();
    var currentSet = new List<T>();
    while (mover.MoveNext())
    {
        currentSet.Add(mover.Current);
        if (currentSet.Count >= size)
        {   
            yield return currentSet;
            currentSet = new List<T>();
        }
    }
    if (currentSet.Count > 0)
        yield return currentSet;
}