Система. InvalidOperationException: Набор был изменен

Моя самая большая ненавистная особенность - любой синтаксис файла конфигурации, который включает условную логику. Подобные вещи распространены в мире Java (муравей, мавен и т. Д. Вы знаете, кто вы есть!).

Вы просто заканчиваете программирование на языке c ** p с ограниченной отладкой и ограниченной поддержкой редактора.

Если вам нужна логика в вашей конфигурации, «Pythonic» подход кодирования конфигурации на реальном языке будет намного лучше.

5
задан yoozer8 13 April 2012 в 17:37
поделиться

6 ответов

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

Вы должны заблокировать свою очередь в начале вашего метода, чтобы другие потоки не изменяли коллекцию, пока вы обращаетесь к ней. Или вы можете заблокировать коллекцию еще до вызова этого метода.

private bool extractWriteActions(out List<WriteChannel> channelWrites)
    {
      lock(tpotActionQueue)
      {
        channelWrites = new List<WriteChannel>();
        foreach (TpotAction action in tpotActionQueue)
        {
            if (action is WriteChannel)
            {
                channelWrites.Add((WriteChannel)action);

                  action.Status = RecordStatus.Batched;

           }
        }
      }
       return (channelWrites.Count > 0);
   }
6
ответ дан 18 December 2019 в 13:17
поделиться

Я думаю, что у меня было аналогичное исключение при использовании цикла foreach в коллекции, где я пытался удалить элементы из Коллекции (а может, это был Список, не помню). В итоге я решил обойти это, используя цикл for . Возможно, попробуйте что-нибудь вроде следующего:

for (int i=0; i<tpotActionQueue.Count(); i++)
{
    TpotAction action = tpotActionQueue.Dequeue();
    if (action is WriteChannel)
    {
        channelWrites.Add((WriteChannel)action);
        lock(tpotActionQueue)
        {
            action.Status = RecordStatus.Batched;
        }
    }
}
8
ответ дан 18 December 2019 в 13:17
поделиться

Я думаю, все, что вам нужно сделать, это перестать использовать foreach и вместо этого переключить его на цикл for

for(int i = 0; i < tpotActionQueue.Length; i++)
{
     TpotAction action = tpotActionQueue[i];

     if (action is WriteChannel)
     {
        channelWrites.Add((WriteChannel)action);
        lock(tpotActionQueue)
        {
           action.Status = RecordStatus.Batched;
        }
     }
}

С уважением, Майк.

0
ответ дан 18 December 2019 в 13:17
поделиться

У вас нет определения для tpotActionQueue , но если это обычный List , то эта строка не ваша проблема. Изменение коллекции - это добавление или удаление элементов, а не установка свойства для содержащегося объекта.

У вас есть блокировка (tpotActionQueue) и тег безопасности потоков, поэтому я предполагаю, что есть еще один поток, добавляющий или удаление элементов из tpotActionQueue во время перечисления. Вероятно, вам потребуется синхронизировать эти доступы.

1
ответ дан 18 December 2019 в 13:17
поделиться

Как насчет некоторых возможностей LINQy?

private bool extractWriteActions(out List<WriteChannel> channelWrites)
{

   channelWrites= tpotActionQueue.Where<WriteChannel>(x => x is WriteChannel).ToList()

   foreach(WriteChannel channel in channelWrites) {
      channel.Status = RecordStatus.Batched;
   }

  return ( channelWrites.Count > 0);
}
0
ответ дан 18 December 2019 в 13:17
поделиться

Я думаю, у вас должен быть другой поток, изменяющий tpotActionQueue, пока вы повторяете его. Поскольку вы блокируете эту очередь только внутри цикла for, это возможно.

-1
ответ дан 18 December 2019 в 13:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: