Updating values in Grasshopper document from thread

I want to find and update the value of a slider in GH from a thread I just created (and which must keep running). I use the following code:

Thread receivingThread = new Thread(new ThreadStart(ReceiveData));
receivingThread.IsBackground = true;
receivingThread.Start();

----- other stuff -----

ReceiveData(){
 while(true){
   -------- getting the guid and val -------
        GH_NumberSlider component = GHdoc.FindObject<GH_NumberSlider>(guid, true);
        slider.Slider.Value = (decimal)val;
  }
}

Whenever I do this Grasshopper displays a warning which says: System.InvalidOperationException: cross-thread operation not valid: Control 'Canvas' accessed from thread other than the thread it was created on.
How can I make the main thread perform the update? How could I pass guid and val to it?

Hi,

this is a more general problem. If you modify something on a GUI, you should always do that on the GUI thread.In order to invoke any action from another thread on the gui thread you need to get access to the ‘Dispatcher’ object and invoke = shedule/request to execute something. In Rhino/GH you can do it in multiple ways…

using System.Threading;
using System.Threading.Tasks;

[…]

 Task.Run(() =>
 {
        // this anonymous method runs on another thread...
        // simulate work
        Thread.Sleep(300);
        //Execute on UI Thread ->printing some text on the Rhino command console
        Rhino.RhinoApp.InvokeOnUiThread(new Action(() =>
        {
            Rhino.RhinoApp.Write("From another task (InvokeOnUiThread): 0.3 sec passed\n");
        }));

        // The same...
        Thread.Sleep(500);
        Grasshopper.Instances.ActiveCanvas.Invoke(new Action(() =>
        {
            Rhino.RhinoApp.Write("From another task (ActiveCanvas.Invoke): 0.8 sec passed\n");
        }));
});

If you work with static fields in between threads, make sure to use the ‘volatile’ keywork. To synchronise threads look at AutoResetEvents, Mutexes, Locks and Events in general. Or use the synchronisation features of the Threading.Tasks namespace

1 Like