RevitAPI:不要在遍历(Iterate)过滤出来的收集器(FilteredElementCollector)时修改文档(Document)

有客户报了一个问题,说用API加载族(Familly)的时候,如果这个文件是一个新的文件,那不会出现问题,但是如果是升级文件,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);
}

首先过滤出来所有的族Family,然后去本地路径里面搜索对应于这个族的.rfa文件,然后调用Document.LoadFamily来Load这个.rfa文件。

我试着在每次调用ReloadFamily之前,输出对应的elem的Id和名字,

while (itr.MoveNext())
{
    Element elem = (Element)itr.Current;
    WriteLog(elem.Id + ":" + elem.Name);
    ReloadFamily(rvtApp, rvtDoc, elem);
}

输出之后发现,有的Id会出现两次,而且出现两次之后,Revit就崩溃了。

那么一定是这个“两次”造成的问题。

思考是不是collector里面的元素有重复呢?重写代码把所有的elem的id都打印出来,发现并没有重复。

又试了另外一种办法,不是用Iterator,而是使用foreach,

foreach (var elem in collector.ToElements())
{
    ReloadFamily(rvtApp, rvtDoc, elem);
}

发现Revit不会崩溃,程序可以正常跑通了。

聪明的读者一定知道foreach一定不会对结果产生影响,而是这里的ToElements()方法,该方法创建了一个新的集合。

原因已经浮现,那就是我们在遍历collector的同时,对Document进行了修改,正是这个修改造成了Revit的崩溃。

举个简单的例子,看下面的代码:

List<int> ids = new List<int>() { 1, 2, 3, 4 };
foreach (int id in ids)
{
    ids.Add(5); //Exception!!!
}
当我们遍历ids的时候,对ids本身进行添加或者删除元素的操作会抛异常:

System.InvalidOperationException: 集合已修改;可能无法执行枚举操作。

同样的道理,对Revit文档进行遍历操作的时候,增加或删除Revit的元素,也会造成相同的问题。

所以,以后遍历文档的时候,大家需要注意哦。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值