When I started my plugin about 16 years ago, the standard guidance was to use rhino commands to execute most code in your plugin, maybe for anything that worked with geometry - I can’t remember exactly, and I haven’t found anysimilar guidance today. A lot has happened since then (introduction of rhinocommon, grasshopper, eto, rhino.inside, etc.) and I’m now having difficuly using my old simulation running command and getting what I want out of the UI (getting the UI to update while I’m running my simulation in ‘runcommand’).
I think what I need to be able to do is run code in the runcommand method asynchronously, but there doesn’t seem to be an obvious way to do that. Basically, I have two graphs that the user needs to see as the simulation runs. The graphs are in a window that updates periodically. This worked in Windows forms using the rhino command to execute, but with eto, the interface is blocked, because the UI thread is tied up in ‘Runcommand.’
So, my question - from c#, is it still recommended that certain code always be run from inside a command? Is it possible I would be better served by moving my simulation running code to a shared method and running it from within my UI panel control instead of running a silent command that manages the simulation?
Thanks in advance!
I would recommend that you have a static class to maintain the state of your code, and use the command to just “start” the process. Your UI Panels can read the state of your plugin from the static class and react accordingly.
You could have a couple commands, a start, and a stop maybe depending on what you are trying to do. So long as you are running in a command, you will be limited to what other operations you can do in Rhino at the same time. (such as running other scripts, etc.)
If you go the route of threads you will still need to invoke back onto the Rhino main UI thread for Geometry operations. Also the Document object is not thread safe, and has to only be manipulated on the UI thread.
Historically, we would start several threads from a .Begin() method in each simulation class (which inherits from a parent class ’ Simulation’) . Then the command watches the simulation status from a loop. The same method is used to call ray-tracing, image source, direct sound, and Finite Volume Method. Of course, this loop is what blocks the UI thread.
It sounds like you are advocating that you can start it with the command, and then exit the command, but watch the simulation from a UI element. That’s fine, but is the command needed at all, then? Right now, we call it from Rhino.Rhinoapp.Runscript(), and it’s a silent command that doesn’t show up in autocomplete, and doesn’t do anything if the user tries to type it in.
The one thing that I know of that is kind of useful is that the command will block the user from changing the circumstances of the model during a simulation, which I imagine avoids a lot of confusion… Based on some other threads I’ve read on the forum, there may be a way to do something similar, though it probably isn’t simple.
Are there other reasons?
The command isn’t needed, they can just be useful if your UI isn’t yet open/showing to start the process.
You can also set the commands as “test” commands, so they don’t show in the command prompt in rhino, until you type “T_E_S_T” to enable test commands. This makes it easier as a developer to be able to run the commands if needed.
But if you already have UI up you wouldn’t need the commands. The only thing you need to make sure of is if your code is not executing on the main UI thread, and you need to update UI or Geometry in Rhino, that you invoke onto the UI thread to run that code.
If you are running inside of a command, the Rhino Idle loop won’t execute, which can prevent other parts of Rhino (and other plugins) from doing their updates.
I believe when you run inside a Rhino Command you also get an Undo Buffer for free. So you would need to manage undo/redo manually if you were not running in the context of a command.
Running in a command likely also has implications as it relates to Rhino History if that is something you want to make use of on Rhino Objects.
Ok. Thanks. None of that is really useful to my simulations, so it sounds like I can move my simulation starter somewhere else.
I remember test commands. I thought they were gone. At present, my runsim command has the following attribute attached:
But the command may go away altogether now…
Yeah, sorry they used to be called test commands, but the same command still shows Hidden commands.
I’ll wait to see if McNeel responds also, but I appreciate your help!