Я довольно часто использовал BackgroundWorkers, но никогда раньше не сталкивался с этой проблемой. Моя программа анализирует выходные данные логического анализатора, генерирующего пакеты, которых насчитывается тысячи. Чтобы предотвратить слишком большую задержку обновления ListView в моей форме (я ранее сообщал о каждом из них, как он был найден, и форма полностью не отвечала) я собираю пакеты внутри BackgroundWorker в общий список (List ) затем сообщая, что либо когда найдено n значений (в настоящее время 250), либо когда возникает исключение, либо когда оно завершается.
Проблема возникает в моем обратном вызове, когда я выполняю итерацию по списку. Я получаю исключение InvalidOperationException с ошибкой "Коллекция была изменена". Я не касаюсь коллекции внутри foreach (я добавляю в другую коллекцию, но не вижу причин, по которым это могло бы изменить коллекцию, которую я перебираю - плюс ее комментирование не решает проблему.) даже попытался заблокировать e.UserState, сохранить e.UserState в локальной области видимости List и заблокировать его, кажется, ничего не работает.
Вот код для моего метода обратного вызова:
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar.Value = e.ProgressPercentage;
packetsListView.SuspendLayout();
lock ((List<Packet>)e.UserState)
{
foreach (Packet packet in (List<Packet>)e.UserState)
{
packets.Add(packet);
ListViewItem item = new ListViewItem(string.Format("{0}ns", Math.Round(packet.StartSampleNumber * 41.666667)));
item.Tag = packet;
item.SubItems.Add(new ListViewItem.ListViewSubItem(item, packet.Description));
packetsListView.Items.Add(item);
}
}
packetsListView.ResumeLayout();
statusLabel.Text = string.Format("Analyzing...found {0} {1}", packetsListView.Items.Count, packetsListView.Items.Count == 1 ? "packet" : "packets");
}