Manual Regeneration Option Danger

Here is a serious issue that several developers have already run into when migrating to the Revit 2011 API, including myself.
It sometimes causes pretty obscure errors which are hard to understand and very easy to resolve, once you understand the source.
Obviously it is best and most efficient to completely avoid running into the problem at all, which I hope this post will help you do.

The issue is the regeneration option, one of the required attributes that must be set on every external command in this version.

For instance, when

porting The Building Coder samples

to
Revit 2011,
I globally set the regeneration option to manual, e.g.


[Transaction( TransactionMode.Automatic )]
[Regeneration( RegenerationOption.Manual )]
class CmdCollectorPerformance : IExternalCommand
{
  . . .

This is a very risky choice to make, since the manual regeneration mode will cause different behaviour than in Revit 2010.

The less risky choice is to set it to automatic, since that will retain the same behaviour experienced in the Revit 2010 API.
If you use manual regeneration mode and your code makes any change to the Revit model and then queries it for data that has been affected by the changes, the returned data will be stale, i.e. out of date.

If in doubt, when migrating moderately complex code to the new version, the safer choice is to always use the automatic mode instead.
One very minor disadvantage of this is that this issues a warning during compilation:

  • warning CS0618: ‘Autodesk.Revit.Attributes.RegenerationOption.Automatic’ is obsolete:
    ‘Use of RegenerationOpton.Automatic is deprecated and will be removed in a future release.
    Autodesk recommends converting all Revit API code to use the RegenerationOption.Manual option.’

I chose the manual mode for my sample code for several reasons:

  • To avoid this compilation warning.
  • Knowing that almost all of the sample commands are very short and trivial in nature and do not modify the model and query it for data afterwards.
  • Knowing that this is not production code.

This choice did cause a problem in one of the Revit API introduction labs, Lab2_0_CreateLittleHouse, which adds several building elements to the model and in some cases modifies them afterwards.
The area which initially did not work at all and actually threw an exception during execution was the section setting the roof slope:


FootPrintRoof roof = createDoc.NewFootPrintRoof(
  profile, levelTop, roofType, out modelCurves );
double slopeAngle = 30 * LabConstants.DegreesToRadians;
foreach( ModelCurve curve in modelCurves )
{
  roof.set_DefinesSlope( curve, true );
  roof.set_SlopeAngle( curve, slopeAngle );
}

This code creates a new roof, which returns the automatically generated roof edge curves in the modelCurves array.
It then iterates over them to set the DefinesSlope and SlopeAngle properties on each.
This worked perfectly well in Revit 2010, and also in 2011 with automatic regeneration mode.
With the manual mode, however, it causes the following error:

  • Unable to access curves from the roof sketch.

The reason is that the model has been modified by the addition of the model curves, but these changes have not yet propagated far enough through the model for us to already access and modify their properties.
This can easily be resolved once you understand the problem, which simply consists in the addition of a call to doc.Regenerate:


FootPrintRoof roof = createDoc.NewFootPrintRoof(
  profile, levelTop, roofType, out modelCurves );
doc.Regenerate();
double slopeAngle = 30 * LabConstants.DegreesToRadians;
foreach( ModelCurve curve in modelCurves )
{
  roof.set_DefinesSlope( curve, true );
  roof.set_SlopeAngle( curve, slopeAngle );
}

I discussed another example of using

manual regeneration mode
with
Marcelo Quevedo to update the model after a call to SetLocationPoint on a column.
In that case, Marcelo again decided to add appropriate calls to doc.Regenerate to keep the model in synch.

In yet another recent case, Winston Yaw of

RISA Technologies
had
a problem accessing the analytical model curve of a newly created slanted column.
Again, the problem was the regeneration option being set to manual.
Once it was set to automatic, everything worked perfectly.
Another issue that Winston encountered that was also caused by the manual regeneration option was setting the vertical projection parameter for a new slab.

In summary, please be aware of the effect of the regeneration option on your code.
If in any doubt whatsoever, when migrating existing code to the Revit 2011 API, your safest bet will be to set it to automatic.


Comments

13 responses to “Manual Regeneration Option Danger”

  1. If automatic regeneration will be going away in a future release, one would think the only thing a responsible developer whose code will need to work beyond Revit 2011 can do is to deal with this issue NOW, while the code is as small and simple as it is likely to ever be, compared to the future.
    That being the case, developers will need to know (soon) what the official Best Practices are for maximizing the life of existing code in a manual regeneration world.
    Is it to call for a regeneration after every change, or every group of query-free changes?
    That seems difficult to remember as you’re writing code…
    One would assume there is a performance cost for calling for a manual regeneration. Is it usually significant?
    Would an application that makes many query-free changes in a row, then call for one regeneration at the end, get better performance than one that is running in Automatic mode? One would think so, if in Automatic mode a regeneration is happening after each change. But without knowing the general performance impact level of a regeneration, one has to ask: Would it even be noticeable?
    Being aware of the situation is great (thank you very much!), but it would be nice if developers of long-term code could get some more extensive/explicit guidance.

  2. Jon Smith Avatar
    Jon Smith

    Interesting post – we’ve also had some bizzare, and seemingly unrelated, error messages caused by not regenerating.
    Should AutoJoinElements be called with most Regenerate calls? We have done so in our code to be safe, but are not sure yet of the performance impact of this, and whether it is even required – does AutoJoinElements just affect the graphical display or can it affect queries on objects as well?
    Thanks
    Jon Smith

  3. Dear Jon,
    Thank you, I am glad you find it interesting. That was indeed my intention :-)
    I asked the development team, and they responded as follows:
    It is not always needed, however, if you are creating/manipulating walls, roofs, floors, and/or structural framing, and if the exact lengths and geometry of these items after joining is important to you, you will want to call it explicitly. Otherwise the elements will not be at their “final state” before you extract their data – unlike with missing a Regenerate the elements should be self-consistent, but they may be different than the user ultimately sees.
    Cheers, Jeremy.

  4. Jon Smith Avatar
    Jon Smith

    Thanks for finding out Jeremy – sounds like we are best off calling AutoJoin in our situations – just to be safe!
    Cheers
    Jon

  5. Dear David,
    Thank you for your valuable input that I fully agree with. Here is the feedback I received so far after passing on your suggestions to the development team. I will be very interested to follow any hopefully fruitful ensuing discussions and hope that we can get some guidelines or best practices such as you desire put together:
    1. The “best practice” is to use manual regeneration and invoke regeneration only when needed. For example, regenerate must be called before reading data from a changed model.
    The performance of regeneration will depend on the magnitude of change and the complexity of the model – there is no simple and generic answer about how long regeneration will take.
    2. It’s difficult ;-) I do not think there is one best approach. An Ideal approach could differ from an application to application. There are a few solid points though that programmers could use as a reference:
    – Manual mode can only be faster than automatic.
    – Typically, performance increase in manual mode is likely to be significant, especially which changes performed in a loop.
    – Regeneration when nothing needs to be regenerated is rather fast, hence not so costly.
    – Querying data does not require regenerations unless there was a previous change to the part of the model that could affect the data being queried – that is sometimes hard to estimate, though.
    I think this provides a very useful starting point, at least.
    In fact, I think these considerations and suggestions important enough to be promoted to an own blog post.
    Cheers, Jeremy.

  6. It would be nice if there were some type of “RegenerationNeeded” boolean method available.
    But it seems like there may be better ways for Revit to do this. For example, it would be GREAT if “Automatic” mode stayed, but changed how it worked: not be calling Regenerate internally after every change, but rather to have Revit simply call Regenerate INSTEAD of throwing an exception that is caused by the need for a Regenerate.
    Thus Regenerate would only get called when needed, and automatically by Revit, thus maximizing performance, without any special knowledge needed by the developer.
    To me, if that were possible it seems like the best of both worlds.

  7. Jeremy and All,
    In my personal opinion, most of the cases the Automatic mode will solve the problem.
    Revit should be smart enough to just refresh those changed elements. This is related on how the Reactor mechanism is connected to the regeneration mechanism and how it monitors the changed elements.
    I really think it is strange to introduce a concept (this new “Automatic” Attribute) already marked as “to be removed soon”. This will freak people and no one will use it (I have used because I don’t want to review my code because it won’t cause any significant impact). I believe most of Revit developers won’t do this either.
    I agree with the idea of “Automatic” being kept and just tweaked to work as smart as possible. It will satisfy most of the cases and just when the user wants to really avoid the auto Regeneration he should change the attribute to “Manual” and handle his code flow.
    Another approach would be to create something like a PUSH/PULL Auto refresh feature which would empower the user to have control when to turn off auto refresh and when turn it back on after doing his heavy procedures.
    Does not make much sense to obligate people to control a mechanism when most of time its automatic mode will be suitable for them.
    Just my opinion.
    Fernando.

  8. Dear David,
    I am pretty sure that what you wish for is impossible, or the development team would have done just that. When you say “INSTEAD of throwing an exception”, you should be aware that the exception is thrown because of the reason stated in the exception, and there is no way for Revit to realise that this problematic state might be resolved by a regeneration. Keeping track of when a regeneration is required is extremely complex or even impossible.
    Cheers, Jeremy.

  9. Dear Fernando,
    I believe it is a lot more complex than you seem to think :-)
    Also, the automatic option is not new. That is the mode that Revit has been using all along so far. Developers complained that it is too slow, so we introduced the SuspendUpdating mechanism and now the manual option, providing more and more optimisation possibilities.
    I forwarded your comment to the development team and hope to have some slightly more in-depth answer for you soon.
    Cheers, Jeremy.

  10. The thing that’s been bothering me is that in some future version developers will be required to have an intimate understanding of this engine, for which Best Practices haven’t been determined yet, and (worse) without that knowledge strange exceptions could get thrown with little idea as to what the real problem is, or how/where to fix it.
    It seems likely that many (most?) developers new to the Revit platform in the future will get very frustrated with strange exceptions until they learn the details of when they’ll need to explicitly call Regenerate. This can only increase the number of ADN support calls as well. If someone has quite a bit of complex code, they may need to send it all to ADN in order for the problem to be detected and a fix determined.
    I like Fernando’s idea of keeping Automatic mode, as the default, but allowing a more advanced developer to turn on and off Automatic mode at will for when they want to have control over the Regenerations.
    If 80% of your code runs just fine with Automatic mode turned on, and you only have to consciously control the regenerations to fine tune the other 20%, that’s a pretty good scenario, I think. It’s even better if 100% of your code runs just fine in Automatic mode.
    Just my two cents.
    Thank you (all) for the great explanations and ideas. This is extremely useful information.

  11. Dear David,
    Thank you for your appreciation, I am really glad that you find this useful.
    As I am sure you noticed, I promoted this discussion and its continuation to an own blog post which I hope helps further resolve these questions:
    http://thebuildingcoder.typepad.com/blog/2010/04/regeneration-option-best-practices.html
    Cheers, Jeremy.

  12. David R Avatar
    David R

    Jeremy, I cannot pull the Regenerate function. I am not able to get the Autodesk.Revit.Db.document using statement to work in my code? My DB does not show a ‘document’ pick in the list of functions and i cannot figure out why. Everything else in my code works but i cannot get the drawing to show the change.

  13. Dear David,
    That sounds pretty weird to me. I suggest you start out from scratch with a new project and exactly follow the steps outlined by the Revit API webcast to create a new external command add-in. Begin from zero, add in your existing bits of functionality step by step, and hopefully the problem will just disappear.
    Cheers, jeremy.

Leave a Reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading