How to refresh the component it self?

For example,if the component listen to a event,and when the event is raised,how to refresh (disable then enable)it self?
Thank you!

If the event comes from code which executes on the UI thread, you can refresh a component by calling ExpireSolution(true); on it.

If the event might come from a secondary thread, you’ll have to invoke a method via the UI thread which expires the solution.

2 Likes

Thank you David,the situation is the component listen to the event from ABB robot,so this situation is the 1st case you mentioned?
thank you

Use InvokeRequired instead. Situations are that either UI event nor robot event are fixed on a certain type of thread.

David @DavidRutten ,I try the expiresolution,but it run the solver again and again and never stop.this is not I want …i just need when the event raised,the solver run only one time.
thank you for help!

This is code:

        protected override void SolveInstance(IGH_DataAccess DA)
        {
            ABBControllerType aBBControllerType = null;
            DA.GetData("ABBController", ref aBBControllerType);
            Controller ctrl = aBBControllerType.Value.Controller;

            string sigName = null;
            DA.GetData("SignalName", ref sigName);

            Signal sig = ctrl.IOSystem.GetSignal(sigName);
        
            if (sig is DigitalSignal)//
            {
                DigitalSignal digitalSignal = (DigitalSignal)sig;
                digitalSignal.Changed += new EventHandler<SignalChangedEventArgs>(sig_changed);
                 float val = digitalSignal.Get();
                 DA.SetData("Value", val);
                 Message = "DI";
             }

             else if(sig is GroupSignal)
             {
                 GroupSignal groupSignal = (GroupSignal)sig;
                 groupSignal.Changed += new EventHandler<SignalChangedEventArgs>(sig_changed);
                 float val = groupSignal.Value;
                 DA.SetData("Value", val);
                 Message = "GI";
             }
       
                 sig.Dispose();
                 return;
              }
         public void sig_changed(object source, SignalChangedEventArgs e)
         {
             ExpireSolution(true);
         }

You have to be careful registering handlers for events, lest you end up with multiple handles.

I imagine the SolveInstance() must do two things:

  1. Ensure the event handler is connected to the event, and only once.
  2. Put data from the most recent event into the output parameters.

Next the eventhandler method may need to make sure that it only triggers a new solution when the incoming event actually represents a change in data. Perhaps the event is called all the time? Also since you may not know for sure whether the event comes in on the UI thread, definitely be safe and reroute it via RhinoApp.InvokeOnUiThread.

David @DavidRutten
i try this code:

public class TestTimer : GH_Component
{
    private static Timer aTimer;

    private  void SetTimer()
    {
        aTimer = new System.Timers.Timer(1000);
        aTimer.Elapsed += OnTimeEvent;
        aTimer.AutoReset = true;
        aTimer.Enabled = true;
    }
    private  void OnTimeEvent(object source ,ElapsedEventArgs e)
    {
        Message = $"{DateTime.Now.TimeOfDay}";
        ExpireSolution(true);
    }
    protected override void SolveInstance(IGH_DataAccess DA)
    {
        SetTimer();
    }
    ////....ignore the unimportant code 
    }
}

the component can update its UI,but after several seconds the whole program go to error…
do you know why? i only know that the Timer is on a new thread.
thank you

Yeah you can’t call ExpireSolution from a non-UI thread. Either route your call through RhinoApp.InvokeOnUiThread(), or use GH_Document.ScheduleSolution() with a callback which expires your object.

2 Likes