Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Modify Shared Parameters for high number of family instance

3 REPLIES 3
Reply
Message 1 of 4
f.djiomejoungleroi.Ext
335 Views, 3 Replies

Modify Shared Parameters for high number of family instance

Hello,
I have the code below working fine when my collection contain less than 30 objet; above 30 the transaction commit doesn't affect document and there is no error or exception raised. Did some one have an idea to solve this?

void IExternalEventHandler.Execute(UIApplication app)
{
	UIDocument uidoc = app.ActiveUIDocument;
	Document doc = uidoc.Document;
	View view = doc.ActiveView;

	using (Transaction tr = new Transaction(doc))
		{
			Parameter param1 = null;
			Parameter param2;
			Parameter param3 ;
			Parameter param4 = null;
			Parameter param5 = null;
			Parameter param6 = null;
			Parameter param7 = null;

			tr.Start("synchro");
			
			for(int i = 0; i < Main.idForSynchros.Count; i++) // Main.idForSynchro is the collection of data
			{
				IdForSynchro idForSynchro = Main.idForSynchros[i];
				Element element = doc.GetElement(new ElementId(Convert.ToInt32(idForSynchro.RevitId)));

				param1 = element.LookupParameter("PLUGIN_PARAM1");
				param2 = element.LookupParameter("PLUGIN_PARAM2");
				param3 = element.LookupParameter("PLUGIN_PARAM3");
				param4 = element.LookupParameter("PLUGIN_PARAM4");
				param5 = element.LookupParameter("PLUGIN_PARAM5");
				param6 = element.LookupParameter("PLUGIN_PARAM6");
				param7 = element.LookupParameter("PLUGIN_PARAM7");

				if (param1.AsInteger() < 1)
				{
					param1.Set(idForSynchro.param1);
				}

				string param6Value = DateTime.Parse(idForSynchro.data.param6, CultureInfo.InvariantCulture).ToLongDateString();
				string param7Value = DateTime.Parse(idForSynchro.data.param7, CultureInfo.InvariantCulture).ToLongDateString();

				Utils.SetParameterValueString(param2, idForSynchro.data.param2);
				Utils.SetParameterValueString(param3, idForSynchro.data.param2);
				Utils.SetParameterValueString(param4, idForSynchro.data.param4);
				Utils.SetParameterValueString(param5, idForSynchro.data.param5);
				Utils.SetParameterValueString(param6, param6Value);
				Utils.SetParameterValueString(param7, param7Value);                     

			}
			tr.Commit();
		}
}

// Method of Utils class that set Parameter value
 public static void SetParameterValueString(Parameter parameter, string value)
{
	if (parameter != null)
	{
		parameter.Set(value);
	}
}
3 REPLIES 3
Message 2 of 4

LookupParameter is unnecessarily costly.

 

There is no need to re-execute it for every parameter on every single element.

 

That is costing you a lot of time and hurting performance.

 

Every shared parameter is equipped with a GUID to identify it.

 

Determine the GUID once only on the first element.

 

Then, you can use the GUID to retrieve each parameter directly from the element without any LookupParameter searching through the entire list of parameters each time.

 

Here is my suggestion for an improvement:

 

    class IdForSynchro
    {
      public ElementId RevitId { get; set; }
      public int Param1 { get; set; }
      public string Param2 { get; set; }
      public double Param3 { get; set; }
    }

    void modifyParameterValues( Document doc, IList<IdForSynchro> data )
    {
      using( Transaction tr = new Transaction( doc ) )
      {
        Guid guid1 = Guid.Empty;
        Guid guid2 = Guid.Empty;
        Guid guid3 = Guid.Empty;

        tr.Start( "synchro" );

        foreach( IdForSynchro d in data )
        {
          Element e = doc.GetElement( d.RevitId );

          if( Guid.Empty == guid1 )
          {
            guid1 = e.LookupParameter( "PLUGIN_PARAM1" ).GUID;
            guid2 = e.LookupParameter( "PLUGIN_PARAM2" ).GUID;
            guid3 = e.LookupParameter( "PLUGIN_PARAM3" ).GUID;
          }
          e.get_Parameter( guid1 ).Set( d.Param1 );
          e.get_Parameter( guid2 ).Set( d.Param2 );
          e.get_Parameter( guid3 ).Set( d.Param3 );
        }
        tr.Commit();
      }
    }

 

I added this code in the original and updated forms to The Building Coder samples.

 

Here is the diff between the two:

 

https://github.com/jeremytammik/the_building_coder_samples/commit/fea7381f51b660fc9b5660c2e64f548623...

 

Here is the current code there:

 

https://github.com/jeremytammik/the_building_coder_samples/blob/master/BuildingCoder/BuildingCoder/C...

  

Please let us know whether this helps.

 

Please equip your code with a little benchmark timer stopwatch and let us know the processing time required before and after making this modification.

 

Thank you!

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 3 of 4

Thank you Jeremy,

I apply the solution and got  execution time improved. here is some results before and after the modification.

Number of Family instance

Time before (ms)

Time After(ms)

58

896

794

375

1958

1549

1052

16777

8152

But there are always times when changes are not applied to the document.

 

Message 4 of 4

Not sure if you caught it when you refactored, but in your original code you used param2 to set 2 and 3. Could that be affecting what your results are?

 

May be good to throw in some Try/Catch block to try and see where or if it's failing or at least a Task dialog to tell user if a param is missing.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Rail Community