Async recompute grasshopper component in Rhino.Inside

Hi,

I am trying to program a component that is running async inside Rhino.Inside Revit. What I notice is the typical ways to expire a component (that work inside grasshopper normally) don’t seem to work within Revit, in that the wires go orange but the solution doesn’t update. I have tried:

Rhino.RhinoApp.InvokeOnUiThread(new Action(() =>
{
    this.ExpireSolution(true);
}));

and

Rhino.RhinoApp.MainApplicationWindow.Invoke((Action)delegate
{
    ExpireSolution(true);
});

I assume its a threading issue or something inside Revit. Does anyone know a workaround / solution?

Any help would be greatly appreciated!

Hi @Philip_STockwell,

Revit allows access to its API only during certain “moments”.

Rhino.Inside synchronize itself with these moments when the Rhino window or any child of it, like Grasshopper, is active.
Rest of the time Grasshopper is dormant waiting to have access to Revit API.

Your code should work as long as the Grasshopper window is active but if the window becomes deactivated before the asynchronous operation starts it will run while Grasshopper is dormant.

Could you share more details on what you are trying to achieve?

Hi @kike ,

Thanks for the quick reply (FYI sorry I just realised I replied on another account). What you describe is exactly what I am observing, the code does work (or update) but only when the grasshopper window is active.

My code uses a websocket to receive data from another program so I can ‘push’ commands to grasshopper / revit. What I would like ideally is to have the code run in the grasshopper player or just open the script but essentially have it off screen so the user can essentially use the other program to just push updates to revit.

My final code that I have got working the best ended up using OnPingDocument but I think it all of them had the same effect (as you described that the window needs to be active).

The web socket runts inside a Task.Run(() => using WebSocketSharp and basically when it receives messages

            Task.Run(() =>
            {
                ws = new WebSocket(connectionstring);
                ws.OnMessage += (sender, e) =>
                {
                    messages.Enqueue(e.Data);
                    RhinoApp.InvokeOnUiThread(UpdateSolution);

and update solution:

GH_Document ghdoc = this.OnPingDocument();
if (ghdoc != null)
{
    ghdoc.ScheduleSolution(5);
}

The inside the SolveInstance I run a while to process the messages:

while (messages.TryDequeue(out string msg))
{
//process logic here
}
DA.SetDataTree(0, outputTree);
DA.SetDataList(1, parameterNames);

Is there some way around the window needing to be active?

Does your component run only on the Revit environment or is it a generic one that also runs on Grasshopper standalone?

Hi @kike, just really in revit because I am using it to ‘push’ parameters to edit components in revit. I do also use the component in normal grasshopper for other things but the primary idea is to use it inside revit as a way to control the revit model parameters remotely.

If it came down to having specific components for each use-case I would be ok with this, not hard to code up a similar component.

Hi @phil10,

There are changes on the daily channel on RiR that should enable this.
Please update to RiR 1.27 and try it.

Let me know how it works.

Thanks.

Hi @kike

That seems to be working perfectly based on my initial tests. I’ll keep doing more testing to let you know if I find any issues.

Thanks very much! Phil