Исключение «Коллекция была изменена», когда этого не было

#c# #asynchronous #collections

#c# #асинхронный #Коллекции

Вопрос:

Я получаю это исключение с помощью этого кода и не могу понять, почему

 private static void LoopBTCtx()
{
    Task.Factory.StartNew(async () =>
    {
        while (true)
        {
            try
            {
                Thread.Sleep((int)TimeSpan.FromSeconds(10).TotalMilliseconds);

                List<(string, SocketMessage, int)> _btcTX = btcTX;

                foreach (var tx in btcTX)
                {
                    int newConfirmations = GetBTCtxConfirmations(tx.Item1);

                    if (tx.Item3 != newConfirmations)
                    {
                        _btcTX.Remove(tx);

                        if (newConfirmations < 6)
                        {
                            _btcTX.Add((tx.Item1, tx.Item2, newConfirmations));
                        }

                        await tx.Item2.Channel.SendMessageAsync($"{tx.Item2.Author.Mention}, ``{tx.Item1}`` now has **{newConfirmations}**/6 confirmation{(newConfirmations != 1 ? "s" : null)}.");
                    }
                }

                btcTX = _btcTX;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }
    });
}
  

Оно выдается после обработки первого элемента списка ( foreach )

Строка исключения из трассировки стека — это строка, содержащая foreach (var tx in btcTX)

Я попытался использовать 2 разных списка, а затем обновить основной после foreach завершения, как вы можете видеть в моем коде выше, но это не исправило.

Ответ №1:

У вас все еще есть один список. Следующий оператор просто заставляет _btcTX указывать на тот же экземпляр списка, что и btcTX:

 List<(string, SocketMessage, int)> _btcTX = btcTX;
  

Итак, на самом деле основной список был изменен в Remove() и / или Add().
Один из способов удалить / добавить элементы — выполнить обычный цикл for с индексом (от последнего к первому), и тогда вы сможете удалять / добавлять элементы без проблем.
Другим способом было бы сохранить цикл foreach, но сохранить удаляемые индексы и добавляемые элементы внутри цикла, а затем выполнить фактическое добавление / удаление после цикла (удаление должно выполняться от последнего индекса к первому).

Комментарии:

1. О, так что проблема заключалась в том, что она указывала на тот же список, я действительно думал, что он создаст новый, с теми же элементами из другого. Большое спасибо !