Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/278.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/25.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# 随着时间的推移,并行ForEach只消耗很少的处理能力_C#_.net_.net 4.0_Parallel Processing - Fatal编程技术网

C# 随着时间的推移,并行ForEach只消耗很少的处理能力

C# 随着时间的推移,并行ForEach只消耗很少的处理能力,c#,.net,.net-4.0,parallel-processing,C#,.net,.net 4.0,Parallel Processing,我运行了下面的代码,随着时间的推移(一到两个小时),我注意到遍历这些项所花费的时间越来越长。我正在做什么导致了这种情况的发生?如果是这样的话,我如何修复它 int totalProcessed = 0; int totalRecords = MyList.Count(); Parallel.ForEach(Partitioner.Create(0, totalRecords), (range, loopState) => {

我运行了下面的代码,随着时间的推移(一到两个小时),我注意到遍历这些项所花费的时间越来越长。我正在做什么导致了这种情况的发生?如果是这样的话,我如何修复它

        int totalProcessed = 0;
        int totalRecords = MyList.Count();

        Parallel.ForEach(Partitioner.Create(0, totalRecords), (range, loopState) =>
        {
            for (int index = range.Item1; index < range.Item2; index++)
            {
                DoStuff(MyList.ElementAt(index));
                Interlocked.Increment(ref totalImported);
                if (totalImported % 1000 == 0)
                    Log(String.Format("Processed {0} of {1} records",totalProcessed, totalRecords));
            }
        });

         public void DoStuff(IEntity entity)
         {
              foreach (var client in Clients)
              {
                  // Add entity to a db using EF
                  client.Add(entity);
              }
          }
inttotalprocessed=0;
int totalRecords=MyList.Count();
Parallel.ForEach(Partitioner.Create(0,totalRecords),(range,loopState)=>
{
对于(int index=range.Item1;index

感谢您的帮助

ElementAt
是一种非常缓慢的扩展方法,具有以下实现:

public static void T ElementAt(this IEnumerable<T> collection, int index) 
{
    int i = 0;
    foreach(T e in collection)
    {
        if(i == index)
        {
            return e;
        }
        i++;
    }
    throw new IndexOutOfRangeException();
}
公共静态void T ElementAt(此IEnumerable集合,int索引)
{
int i=0;
foreach(集合中的T e)
{
如果(i==索引)
{
返回e;
}
i++;
}
抛出新的IndexOutOfRangeException();
}

很明显,索引越大,它的工作时间越长。您应该使用indexer
MyList[index]
而不是
ElementAt

,正如@mace所指出的那样,使用
ElementAt
存在性能问题。每次调用该函数时,迭代器都从
MyList
的开头开始,跳过n个元素,直到到达所需的索引。随着指数位置越来越高,情况会越来越糟

如果您仍然需要对
MyList
进行流式访问,可以通过使用
跳过
获取
来缓解性能问题。当您在
MyList
中寻找一个职位时,仍然会有一些性能影响,但是
Take
将确保您在到达那里后获得一批元素,而不是对每个元素都这样做

我还注意到,您使用的是分区样式foreach,但是您在整个范围内都在使用它。在下面的示例中,我使用批处理实现了分区样式

int totalRecords = MyList.Count();
int batchSize = 250;

Parallel.ForEach(Partitioner.Create(0, totalRecords, batchSize), range =>
{
    foreach (var thing in MyList.Skip(range.Item1).Take(batchSize))
    {
        DoStuff(thing);

        //logging and stuff...           
    }
});
更新

再次阅读该问题后,您可能会遇到以下问题:太多线程被用于可能是IO限制的问题,即网络,然后是DB\disk。我这样说就像你说CPU利用率很低一样,这让我觉得你在IO上被阻塞了,而且情况越来越糟

如果纯粹是
ElementAt
,您仍然会看到高CPU利用率

配置
MaxDegreeOfParallelism
以调整要使用的最大线程数:

const int BatchSize = 250;

int totalRecords = MyList.Count();
var partitioner = Partitioner.Create(0, totalRecords, BatchSize);
var options = new ParallelOptions { MaxDegreeOfParallelism = 2 };

Parallel.ForEach(partitioner, options, range =>
{
    foreach (int thing in MyList.Skip(range.Item1).Take(BatchSize))
    {
        DoStuff(thing);

        //logging and stuff...           
    }
});

你能发布一些关于“DoStuff”内部发生了什么的详细信息吗?好的,我已经编辑了我的代码,将“DoStuff”内部发生的事情包括在内。+1最近我看到一些人被ElementAt绊倒了。它应该附有健康警告。