Не добавляйте и не удаляйте элементы при перечислении коллекций элементов
Пользователь столкнулся с проблемой, что при загрузке семейства через API, Revit закрывается.
Вот его код:
- UIApplication rvtApp = commandData.Application;
- UIDocument rvtDoc = rvtApp.ActiveUIDocument;
- FilteredElementCollector collector =
- new FilteredElementCollector(rvtDoc.Document)
- .OfClass(typeof(Family));
- FilteredElementIterator itr =
- collector.GetElementIterator();
- while (itr.MoveNext())
- {
- Element elem = (Element)itr.Current;
- ReloadFamily(rvtApp, rvtDoc, elem);
- }
Сначала выбираются все семейства, затем ищется соответствующий .rfa файл. Если он найден, то вызывается загрузка этого семейства с помощью метода Document.LoadFamily.
Мне удалось воспроизвести проблему, и я попытался выяснить в чем же причина.
Для начала я получил идентификаторы семейств, перед тем как вызывать метод ReloadFamily.
- while (itr.MoveNext())
- {
- Element elem = (Element)itr.Current;
- WriteLog(elem.Id + ":" + elem.Name);
- ReloadFamily(rvtApp, rvtDoc, elem);
- }
Посмотрев на результат, я обнаружил, что некоторые идентификаторы повторяются и в этом случае Revit падает.
Т.е. причина похоже именно в дубликатах.
Но, я ошибался.
Я попробовал изменить Iterator на foreach:
- foreach (var elem in collector.ToElements())
- {
- ReloadFamily(rvtApp, rvtDoc, elem);
- }
И… Revit больше не падает.
Вероятно, вы поняли, что причина не в foreach, а в методе ToElements(), который фактически создает новую коллекцию.
Таким образом, причина очевидна. Пока мы перечисляем элементы коллекции, мы сделали изменения в проекте, а именно, добавили новые элементы, что и вызвало падение Revit.
Давайте посмотри простой пример с коллекциями:
- List<int> ids = new List<int>() { 1, 2, 3, 4 };
- foreach (int id in ids)
- {
- ids.Add(5); //Исключение!!!
- }
Все мы знаем, что когда мы перечисляем идентификаторы из списка и добавляем элементы в этот же список, то непременно возникнет исключение.
Тоже самое происходит и с документом Revit, когда мы перечисляем элементы из проекта.
Итог: Не добавляйте и не удаляйте элементы при перечислении элементов проекта, за исключением случаев, когда вы перечисляете копию этой коллекции.
Обсуждение: http://adn-cis.org/forum/index.php?topic=2629
Опубликовано 12.04.2015