Issue with Executing Rhino Commands via Multi-threaded C# Server

Hello!

I’ve encountered a problem when trying to execute Rhino commands using the RhinoApp.RunScript method within a custom C# server. To give some context, I’ve created a custom Rhino plugin that includes a server implemented in C#. This server listens for specific commands, such as moving vertices, which are then executed within Rhino. The server class is derived from Rhino.Commands.Command.

The server class was implemented using the Rhino3D guide “Run a Rhino command from a Plugin”. However, when these commands are executed, Rhino processes the script but doesn’t make any visible changes to the document, likely due to threading issues. It seems Rhino commands executed from a background thread don’t properly sync with the main UI thread. I’m seeking advice on how to properly execute and synchronize these commands in a multi-threaded environment to ensure they work as expected.

Here’s the code structure for starting the server:

using System;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using Rhino;
using Rhino.Commands;
using Rhino.Display;

namespace PlugIn_Modelisation
{
    [CommandStyle(Style.ScriptRunner)]
    public class StartServer : Command
    {
        private static BackgroundWorker _worker;
        public StartServer()
        {
            Instance = this;
        }

        public static StartServer Instance { get; private set; }

        public override string EnglishName => "StartServer";

        protected override Result RunCommand(RhinoDoc doc, RunMode mode)
        {
            RhinoView activeView = doc.Views.ActiveView;
            var shadedMode = DisplayModeDescription.FindByName("Shaded");
            activeView.ActiveViewport.DisplayMode = shadedMode;
            activeView.Redraw();

            Server serveur = Server.build();

            // The issue seems to be related to this part:
            Thread newThread = new Thread(() => serveur.RunServer(doc));
            newThread.Start();

            RhinoApp.WriteLine("Server done");

            return Result.Success;
        }
    }
}

However, I’m facing issues with threading. The RunServer method is called on a separate thread, which seems to cause problems when trying to execute Rhino commands. Here’s a sequence diagram that outlines the current call structure:

Sequence Diagram

What should I change in the Server class to make Rhino execute commands properly?**

You need to run Rhino Commands on rhino main thread. In your server, accept and take requests and put them in a queue. Also in your server listen to RhinoApp.Idle event and when it is called, take requests from your server queue and execute them. The Idle event handler is called by Rhino on its main thread.

You can also use Eto.Forms.Application.Instance.InvokeAsync() to put your action on the UI thread but that works with a Rhino that has ui.

1 Like