1

我将列表分成块并按如下方式处理:

foreach (var partialist in breaklistinchunks(chunksize))
{
  try
   {
       do something
  }
catch
{
print error
}

}



public static class IEnumerableExtensions
    {
        public static IEnumerable<List<T>> BreakListinChunks<T>(this IEnumerable<T> sourceList, int chunkSize)
        {
            List<T> chunkReturn = new List<T>(chunkSize);
            foreach (var item in sourceList)
            {
                chunkReturn.Add(item);
                if (chunkReturn.Count == chunkSize)
                {
                    yield return chunkReturn;
                    chunkReturn = new List<T>(chunkSize);
                }
            }
            if (chunkReturn.Any())
            {
                yield return chunkReturn;
            }
        }
    }

如果有错误,我希望再次运行该块。是否可以找到我们收到错误的特定块号并再次运行?批次必须按顺序执行。因此,如果批次#2 产生错误,那么如果再次失败,我需要能够再次运行 2。我只需要永远退出循环。

4

5 回答 5

4
List<Chunk> failedChunks = new List<Chunk>();
foreach (var partialist in breaklistinchunks(chunksize))
{
    try
    {
        //do something
    }
    catch
    {
        //print error
        failedChunks.Add(partiallist);
    }

}

// attempt to re-process failed chunks here
于 2012-10-25T01:17:17.190 回答
2

我根据Aaron's answer的评论提出这个答案。

批次必须按顺序执行。因此,如果 2 有问题,那么如果再次失败,我需要能够再次运行 2。我只需要永远摆脱困境。

foreach (var partialist in breaklistinchunks(chunksize))
{
    int fails = 0;
    bool success = false;

    do
    {
        try
        {
            // do your action
            success = true; // should be on the last line before the 'catch'
        }
        catch
        {
            fails += 1;
            // do something about error before running again
        }
    }while (!success && fails < 2);

    // exit the iteration if not successful and fails is 2
    if (!success && fails >= 2)
        break;
}
于 2012-10-25T02:41:50.170 回答
1

如果您不介意从 Enumerable 切换到 Queue,我为您提供了一个可能的解决方案,考虑到要求,哪种适合...

void Main()
{
    var list = new Queue<int>();
    list.Enqueue(1);
    list.Enqueue(2);
    list.Enqueue(3);
    list.Enqueue(4);
    list.Enqueue(5);

    var random = new Random();

    int chunksize = 2;
    foreach (var chunk in list.BreakListinChunks(chunksize))
    {
        foreach (var item in chunk)
        {   
            try
            {           
                if(random.Next(0, 3) == 0) // 1 in 3 chance of error
                    throw new Exception(item + " is a problem");
                else
                    Console.WriteLine (item + " is OK");
            }
            catch (Exception ex)
            {
                Console.WriteLine (ex.Message);
                list.Enqueue(item);
            }
        }
    }
}

public static class IEnumerableExtensions
{   
    public static IEnumerable<List<T>> BreakListinChunks<T>(this Queue<T> sourceList, int chunkSize)
    {
        List<T> chunkReturn = new List<T>(chunkSize);
        while(sourceList.Count > 0)
        {
            chunkReturn.Add(sourceList.Dequeue());
            if (chunkReturn.Count == chunkSize || sourceList.Count == 0)
            {
                yield return chunkReturn;
                chunkReturn = new List<T>(chunkSize);
            }       
        }
    }
}

输出

1 is a problem
2 is OK
3 is a problem
4 is a problem
5 is a problem
1 is a problem
3 is OK
4 is OK
5 is OK
1 is a problem
1 is OK
于 2012-10-25T01:37:05.660 回答
0

break一旦块失败两次,您就可以使用退出循环:

foreach (var partialList in breaklistinchunks(chunksize))
{
    if(!TryOperation(partialList) && !TryOperation(partialList))
    {
        break;
    }
}

private bool TryOperation<T>(List<T> list)
{
    try
    {
        // do something
    }
    catch
    {
        // print error
        return false;
    }
    return true;
}

您甚至可以使用 LINQ 将循环变成单线,但是将 LINQ 与副作用结合起来通常是不好的做法,而且它的可读性也不是很好:

breaklistinchunks(chunksize).TakeWhile(x => TryOperation(x) || TryOperation(x));
于 2012-10-25T02:45:42.953 回答
0

一种可能性是使用 for 循环而不是 foreach 循环,并使用计数器作为确定错误发生位置的方法。然后你可以从你离开的地方继续。

于 2012-10-25T01:12:12.107 回答