DynamoRevit icon indicating copy to clipboard operation
DynamoRevit copied to clipboard

Running Dynamo UI-less appears to have thread bugs; perpetual re-execution

Open ThomasMahon opened this issue 4 years ago • 6 comments

If this issue is not a bug report or improvement request, please check the Dynamo forum, and start a thread there to discuss your issue.

Dynamo version

Dynamo 2.0.2

Revit version

R2019

Operating system

Win10

What did you do?

Created a Revit-addin which executes Dynamo scripts via Revit buttons. We're using the DynamoRevitDS library and initializing a DynamoRevit object to pass in the journal file to create the DynamoRevitCommandData which is executed when the Revit button is clicked.

Some of the scripts have UI nodes from packages such as DataShapes and this is how we know the scripts are executing erroneously since the UIs display when the user does anything else in the model; the script is executed again and again, such as clicking a different button, or modify the model.

We dismiss these pop-ups and that seems to clear the problem, but they will continuously appear every time the user does something in Revit - see the attached video for an example.

Its almost like there is some asynchronous event Dynamo is performing and its being raised more than once when it should only be raised once per button click/dynamo script execution. If we try to debug for example, the unexpected executions of the graph never hit any break points in our app; this is what is leading us to believe its a problem with Dynamo running in UI-less mode.

We've done a lot of testing to try and rule out any errors in our application or in the graphs which may be the culprit but there is nothing which appears to be triggering the multiple/perpetual executions. Some more detail:

  1. When JournalKeys.AutomationModeKey = false and when JournalKeys.ForceManualRunKey = true
  • .dyn files which have any nodes that show RevitAPIUI TaskDialog to the user, execute normally. By normally I mean that the messages don't fire again after the .dyn file is ran and any changes are made to the Revit document afterwords by the user.
  • .dyn files which use Winforms, such as Data Shapes which ask for user input before running the script, do not execute normally. For example, after the script is executed successfully, and returns control to the caller, then Data Shape nodes take action and show their UI making them totally out of sync, because the line of code that opens up dynamo and executes the script has already been called by the executing thread.
  1. When JournalKeys.AutomationModeKey = true and when JournalKeys.ForceManualRunKey = false
  • Any script containing either a node which shows a RevitAPIUI TaskDialog or a Winform, do not execute normally. By normally I mean, that after the script is executed successfully and the buttons execute method is popped of the stack, both TaskDialog's and Winforms instantiated by custom nodes keep showing their UI after any changes are made to the current Revit document by the user.
  1. Changing the DYN from Automatic to Manual as part of the button Execute method (by parsing and updating the JSON) also had no effect; the UI messages still continue to display every time the user does something in the model.

  2. Removing any thrid-party packages and using a Python script to open say, a TaskDialog, doesn't resolve the problem.

  3. Instantiating one instance of the DynamoRevit object so it persists throughout the duration of the application has no effect (we cant do this anyway since it needs to update if the user opens another Revit document).

Is this a bug or limitation in running Dynamo in this way? What is also strange is the Dynamo Player does not have this problem running the same scripts. What is different between how Dynamo Player executes scripts and how using the DynamoRevit object executes scripts?

@mjkkirschner @Amoursol @aparajit-pratap your input would be greatly appreciated as finding a solution for this is business critical.

What did you expect to see?

The script executed once.

What did you see instead?

See above.

Video showing problem:

Video of error.zip

ThomasMahon avatar Oct 08 '20 10:10 ThomasMahon

Hi @ThomasMahon - before diving in too far, what you describe seems as designed. If you run a graph in automatic mode, you're starting up a DynamoModel, then just like if the UI was present, attaching a bunch of handlers and updaters that will continue to execute the graph when the document changes.

It's possible some logic in the UI layer is now missing which might have prevented double executions in some cases as well.

What I think you should try, is to shutdown the DynamoModel after the graph is executed.

mjkkirschner avatar Oct 08 '20 19:10 mjkkirschner

The other issue you should consider, is that DynamoRevit and DynamoModel are NOT currently designed in a way that supports multiple instances of either the same process, appdomain etc.

You should be able to reuse the existing DynamoModel which is loaded by Revit.

If you cannot or you must instantiate your own for some reason you must isolate it from the existing one.

mjkkirschner avatar Oct 08 '20 19:10 mjkkirschner

Hi @mjkkirschner

Thanks for the response, its very helpful. I didn't find a reliable way to obtain an instance of the DynamoModel and shutting down the RevitDynamoModel caused exceptions ("ShutDown() can only be called once" for example) and prevented Dynamo from running again (if the Dynamo button was clicked in the Revit ribbon, Dynamo would not launch) in the same Revit session so this wasn't a viable solution, assuming of course, I took the correct approach.

Instead, we just set all the graphs to manual and call ForceRun() on the RevitDynamoModel and that seems to do what we need, so you sent me in the right direction.

Any more information or documentation you can provide for running Dynamo as a background service would be greatly appreciated however, as we are currently having to resort to a lot of trial and error and hit many deadends as barely anything in the libraries shipped by Dynamo have XML documentation. How does Dynamo Player work for example? Is it possible to replace it with our own player? Is any of the player functionality available in any public Dynamo APIs?

ThomasMahon avatar Oct 09 '20 12:10 ThomasMahon

@sm6srw any ideas on what could be different in the execution model of Player vs. Dynamo that could cause multiple executions in Dynamo but not in Player?

aparajit-pratap avatar Oct 21 '20 03:10 aparajit-pratap

EDIT: The below did not work for me :(


~~Stumbled upon this thread as I just ran into this with a user of Data Shapes nodes in UI-less dynamo.~~

~~This seemed to fix it for me:~~ ~~https://github.com/ParallaxTeam/Relay/blob/05b815f1519b6c2a942db2960945108bc187959e/src/Revit/Command.cs#L134~~

~~forgive me if my solution is utterly wrong 🙈~~

johnpierson avatar Jan 08 '21 22:01 johnpierson

Yup, I know! The RevitDynamoModel is a singleton so if you dispose it you basically dispose the Dynamo application (and with it the ability to run any scripts and that includes the ones set to ribbon buttons) and there's no way to reinitialize it without restarting Revit - this also explains why Dynamo can only support one tab/file being open at any 1 time incidentally. The ForceRun() technique is the best option for now.

ThomasMahon avatar Jan 09 '21 12:01 ThomasMahon