I want to highlight a list of elements in a View, so I created the following method:
public static void HighlightElementsInView(Document doc, View view, List<ElementId> eIds)
{
OverrideGraphicSettings overrideGraphicSettings = new OverrideGraphicSettings();
overrideGraphicSettings.SetProjectionLineColor(new Color(255, 0, 0));
overrideGraphicSettings.SetSurfaceForegroundPatternColor(new Color(255, 0, 0));
using(TransactionGroup transactionGroup = new TransactionGroup(doc, "Highlight Elements in View " + view.Name))
{
transactionGroup.Start();
if(view.CanBePrinted)
{
foreach(ElementId eId in eIds)
{
using(Transaction transaction = new Transaction(doc, "Highlight Element " + eId.IntegerValue))
{
transaction.Start();
view.SetElementOverrides(eId, overrideGraphicSettings);
transaction.Commit();
}
}
}
transactionGroup.Assimilate();
}
}
This works fine, but when the number of elements is large (e.g. 15000), the process takes ages or the program crashes. Is there a way to optimize this?
I'm kind of missing a method like "SetElementsOverride" that takes a List of elements and only uses a transaction to modify them all.
Solved! Go to Solution.
Solved by Mohamed_Arshad. Go to Solution.
HI @evidalpe
I have seen two things in your code,
Reference Code:
Approach -01
public static void HighlightElementsInView(Document doc, View view, List<ElementId> eIds)
{
OverrideGraphicSettings overrideGraphicSettings = new OverrideGraphicSettings();
overrideGraphicSettings.SetProjectionLineColor(new Color(255, 0, 0));
overrideGraphicSettings.SetSurfaceForegroundPatternColor(new Color(255, 0, 0));
var enumurator = eIds.GetEnumerator();
using (Transaction transaction = new Transaction(doc, "Highlight Element"))
{
transaction.Start();
while (enumurator.MoveNext())
{
ElementId eId = enumurator.Current;
view.SetElementOverrides(eId, overrideGraphicSettings);
}
transaction.Commit();
}
}
Approach -02
public static void HighlightElementsInView(Document doc, View view, List<ElementId> eIds)
{
OverrideGraphicSettings overrideGraphicSettings = new OverrideGraphicSettings();
overrideGraphicSettings.SetProjectionLineColor(new Color(255, 0, 0));
overrideGraphicSettings.SetSurfaceForegroundPatternColor(new Color(255, 0, 0));
using (TransactionGroup transactionGroup = new TransactionGroup(doc, "Highlight Elements in View " + view.Name))
{
transactionGroup.Start();
using (Transaction transaction = new Transaction(doc, "Highlight Element"))
{
transaction.Start();
if (view.CanBePrinted)
{
foreach (ElementId eId in eIds)
{
view.SetElementOverrides(eId, overrideGraphicSettings);
}
}
transaction.Commit();
}
transactionGroup.Assimilate();
}
}
Additional Links about Nested Transactions : https://forums.autodesk.com/t5/revit-api-forum/looped-transactions-only-committing-the-first-object/...
Kindly use time stamp to get best executing time among the above code.
Hope this will helps 🙂
@Mohamed_Arshad those two approaches improve a lot the performance, so I'm accepting that as a good response, thanks.
My mistake was assuming that each view.SetElementOverrides(eId, overrideGraphicSettings); call needed to be encapsulated in a transaction, so the nesting was the issue. I didn't know that you can modify all elements in a single transaction without crashing. Of course you miss the possibility of undoing each transaction one by one but that does not make sense for a large number of elements.
Between approach 1 and 2, 1 seems to perform a bit better, but just one important note: the enumerator needs to be disposed after its usage.
Hi @evidalpe
According to C#, typically don't need to manually dispose of the IEnumerator obtained from a collection using the GetEnumerator method.
As you told In our case we manually using an IEnumerator and want to ensure proper resource cleanup, it's a good practice to call its Dispose method or we can use using() statements.
Thank you for the complete conversation @evidalpe
Can't find what you're looking for? Ask the community or share your knowledge.