使用Take in while循环

时间:2013-11-06 12:19:16

标签: c#

我有一个包含数千个元素的集合,我做一个for循环来一次处理100个元素然后上传它们并暂停5秒

while (EntriesList.Count > 0)
            {
                service.InsertEntries(EntriesList.Take(100).ToList<Entry>());
                System.Threading.Thread.Sleep(5000);
            }

service.InsertEntries需要List<Entry>作为参数,还有更好的方法来实现这样的事情吗?

通常情况下,我使用带有%运算符和临时列表的for循环,上面是否相同?

5 个答案:

答案 0 :(得分:3)

这将一次又一次插入前100个条目。

跟踪您的位置,并使用Skip继续前进:

int current = 0;
int batchSize = 100;

while (current < EntriesList.Count)
{
    service.InsertEntries(EntriesList.Skip(current).Take(batchSize).ToList());
    current += batchSize;
    System.Threading.Thread.Sleep(5000);
}

答案 1 :(得分:2)

EntriesList.Take(100).ToList()将创建一个包含100个条目的新列表,您不会从EntriesList中删除100个条目。

您可以执行以下操作:

List<TYPE> objectsforupload = EntriesList.ToList();
while (objectsforupload.Count > 0)
{
        List<TYPE> uploadlist = objectsforupload.Take(100).ToList();
        objectsforupload = objectsforupload.Where(x => !uploadlist.Contains(x)).ToList();
        service.InsertEntries(objectsforupload);
        System.Threading.Thread.Sleep(5000);
}

答案 2 :(得分:2)

.Take()

之后调用此方法
EntriesList.RemoveRange(0, Math.Min(EntriesList.Count, 100));

它将删除前100个元素。

编辑:更完整的例子:

while (EntriesList.Count > 0)
{
    var poppedEntries = EntriesList.Take(100).ToList<Entry>();
    EntriesList.RemoveRange(0, poppedEntries.Count);
    service.InsertEntries(poppedEntries);
    System.Threading.Thread.Sleep(5000);
}

答案 3 :(得分:2)

对于这种事情,你应该写一个Chunkify扩展方法。您可以从Marc here获得一个很好的例子。但由于这个问题,它总是返回一个固定大小的数组,也许是空条目。

所以这个实现可能更符合您的要求:

/// <summary>
/// Divides an enumeration into smaller (same-sized) chunks.
/// </summary>
/// <typeparam name="T">The type of the elements within the sequence.</typeparam>
/// <param name="source">The sequence which should be breaked into chunks.</param>
/// <param name="size">The size of each chunk.</param>
/// <returns>An IEnumerable&lt;T&gt; that contains an IEnumerable&lt;T&gt; for each chunk.</returns>
public static IEnumerable<IEnumerable<T>> Chunkify<T>(this IEnumerable<T> source, int size)
{
    if (source == null)
    {
        throw new ArgumentNullException("source");
    }

    if (size < 1)
    {
        throw new ArgumentOutOfRangeException("size");
    }

    return ChunkifyImpl(source, size);
}

private static IEnumerable<IEnumerable<T>> ChunkifyImpl<T>(IEnumerable<T> source, int size)
{
    using (var iter = source.GetEnumerator())
    {
        while (iter.MoveNext())
        {
            var chunk = new List<T>(size);
            chunk.Add(iter.Current);

            for (int i = 1; i < size && iter.MoveNext(); i++)
            {
                chunk.Add(iter.Current);
            }

            yield return chunk;
        }
    }
}

现在您可以按如下方式使用此扩展程序:

foreach(var chunk in EntriesList.Chunkify(100))
{
    service.InsertEntries(chunk);
    Thread.Sleep(5000);
}

答案 4 :(得分:1)

按照目前的情况,你的代码不起作用,你也应该跳过相同的数量和

        while (entries.Count > 0)
        {
            service.InsertEntries(entries.Take(100).ToList<Entry>());
            entries = entries.Skip(100);
            System.Threading.Thread.Sleep(5000);
        }

然而,这表现非常糟糕。 IEnumable&lt;&gt;你从Skip()回来会在每次调用时增加开销。

因此,针对此场景的最佳建议是使用for循环。