3

This code performs extremely long time and in the end, doesn't accomplish its goal - combine element's parameters inside of a schedule. It clearly happens due to a large number of elements of the category "Pipe Fitting" in the project. How to increase the speed? Is it through selecting elements using some scheduled class?

Win Forms GUI is used.

Document revitDoc { get; set; }

            public Form1(Document doc)
            {
                InitializeComponent();

                this.revitDoc = doc;
                //Create a list of the parameters you want your user to choose from 
                List<string> stringParameters = new List<string>
            {
                "GP_Description",
                "GP_Model",
                "GP_Angle"             
            };
                //Add list to comboboxes on form 
                foreach (string parameterName in stringParameters)
                {
                    comboBox1.Items.Insert(0, parameterName);
                    comboBox2.Items.Insert(0, parameterName);
                    comboBox3.Items.Insert(0, parameterName);
                   
                }

            }

        private void button1_Click(object sender, EventArgs e)
        {

            FilteredElementCollector collector = new FilteredElementCollector(revitDoc);
            ElementCategoryFilter filter = new ElementCategoryFilter(BuiltInCategory.OST_PipeFitting);
              
            IList<Element> ducts = collector.WherePasses(filter).WhereElementIsNotElementType().ToElements();

            foreach (Element duct in ducts)
            {
     
                Parameter parameter1 = duct.LookupParameter(comboBox1.Text);
                Parameter parameter2 = duct.LookupParameter(comboBox2.Text);
                Parameter parameter3 = duct.LookupParameter(comboBox3.Text);
               
                List<string> parameterValues = new List<string>();


                if (parameter1 != null)
                {
                    string parameterValue1 = parameter1.AsString();
        
                    if (parameterValue1 != "") parameterValues.Add(parameterValue1);
                               
                }
    
                if (parameter2 != null)
                {
                    string parameterValue2 = parameter2.AsString();
          
                    if (parameterValue2 != "") parameterValues.Add(parameterValue2);
                                       
                }
        
                if (parameter3 != null)
                {
                    string parameterValue3 = parameter3.AsString();
                  
                    if (parameterValue3 != "") parameterValues.Add(parameterValue3);

                }
                   
                if (parameterValues.Count > 0) 
                {
                  
                    string newValue = String.Join(" ,", parameterValues);

                    using (Transaction t = new Transaction(revitDoc, "Set Parameter name"))
                    {
                        t.Start();
                        duct.LookupParameter("Outcome").Set(newValue);
                        t.Commit();
                    }
fysharp
  • 101
  • 7
  • what type is `Document`? – Lei Yang Jul 08 '21 at 07:06
  • Apparently, that's how we work with Revit API. Code snippet above belongs to this class "public partial class Form1 : System.Windows.Forms.Form". These lines are from Command.cs "Document doc = uidoc.Document; Form1 form = new Form1(doc)" – fysharp Jul 08 '21 at 07:11
  • I guess you have checked that the performance slowdown is actually in the `foreach` and not in the few lines of code above it. One thing that can improve performance is to not create new objects inside the loop. You could create `parameterValues` above the loop and just clear it in the loop. I found that doing this can sometime make a difference, but it's not guarantied offcourse. The same goes for the Transaction object – GuidoG Jul 08 '21 at 09:13
  • I notice Button is not async which probably means the comboboxX.Text value you are reading to create the parameters will not be changing. Definitely take it out side of the foreach(Element duct in ducts) Loop. – demoncrate Jul 15 '21 at 14:25

1 Answers1

0

This is untested. The biggest item is the location of the Transaction. I suggest wrapping the foreach loop with the Transaction.

public void Process(Document doc, string text1, string text2, string text3)
{
    FilteredElementCollector collector =
        new FilteredElementCollector(doc)
            .OfCategory(BuiltInCategory.OST_PipeFitting)
            .WhereElementIsNotElementType();

    using (Transaction t = new Transaction(doc))
    {
        if (t.Start("Set Parameter Names") == TransactionStatus.Started)
        {
            foreach (Element elem in collector)
            {
                string newValue = string.Empty;

                Parameter outcomeParam = elem.LookupParameter("Outcome");

                if (outcomeParam == null)
                {
                    continue;
                }

                newValue += this.GetParameterValue(elem, text1);
                newValue += this.GetParameterValue(elem, text2);
                newValue += this.GetParameterValue(elem, text3);

                newValue.TrimEnd(',', ' ');

                outcomeParam.Set(newValue);
            }

            t.Commit();
        }
    }
}

public string GetParameterValue(Element elem, string parameterName)
{
    Parameter param = elem.LookupParameter(parameterName);

    return param == null ? string.Empty : param.AsString() + ", ";
}