Trigger component is nearly impossible to stop when interval is small

If you set the interval on a Trigger Component sufficiently small enough (<= 10ms) and connect it to a simple C# script that is meant for incrementing a number every time it is updated by the Trigger component, it becomes hard or impossible to stop the Trigger component the normal way. I have to start mashing the escape key rapidly to have any hope of stopping the Trigger Component. I have done this type of thing before, when the Trigger component was called the Timer component, and definitely did not have this issue.

Steps to reproduce:

  1. Make a new Grasshopper file.
  2. Place a Trigger Component down on the canvas, set interval to 10ms or less (1ms if you really want to experience this bug)
  3. Place a C# script component down on the canvas.
  4. In the C# script, create a double with a value of 0 outside of the RunScript function. In the RunScript function, simply add a value to the double, and output it from the script component.
  5. Exit the C# script component, hit run on the Trigger component.
  6. Try to pause or stop the Trigger component. Observe how difficult it is, you have to time it between re-triggers. If you picked 1ms as your interval, good luck timing that. The only way to get it to stop, for me, has been to repeatedly mash the ESC key as fast as I can, then I can actually hit the pause button on the Trigger component.

Please check the attached file to see this happen. I can reliably reproduce this. IDK what is going on, but it seems like the Timer component used to “listen” for the user clicking pause at all times, whereas the Trigger component only has a brief moment between triggers to “listen” for that, or something like that.

Trigger Bug.gh (10.5 KB)

I just sent this file to two colleagues also on Rhino 8 same version as me (8.10.24228.13001), one on mac and the other on windows, and neither of them had the same issue as me…

Here is my System Information

Rhino 8 SR10 2024-8-15 (Rhino 8, 8.10.24228.13001, Git hash:master @ f4c93f2b85de4dc69b50ed22f1b0d91445724d03)
License type: Commercial, build 2024-08-15
License details: LAN Zoo Network Node

Windows 11 (10.0.22631 SR0.0) or greater (Physical RAM: 32GB)
.NET 7.0.20

Computer platform: LAPTOP - Plugged in [30% battery remaining]

Hybrid graphics configuration.
Primary display: Intel(R) UHD Graphics (Intel) Memory: 1GB, Driver date: 12-9-2023 (M-D-Y).
> Integrated graphics device with 4 adapter port(s)
- Windows Main Display is laptop’s integrated screen or built-in port
Primary OpenGL: NVIDIA RTX A2000 Laptop GPU (NVidia) Memory: 4GB, Driver date: 3-6-2024 (M-D-Y). OpenGL Ver: 4.6.0 NVIDIA 538.47
> Integrated accelerated graphics device with 4 adapter port(s)
- Video pass-through to primary display device

Secondary graphics devices.
Citrix Indirect Display Adapter (Citrix Systems Inc.) Memory: 0MB, Driver date: 1-23-2019 (M-D-Y).
> External USB display device with 8 adapter port(s)
- There are no monitors attached to this device. Laptop lid is probably closed

OpenGL Settings
Safe mode: Off
Use accelerated hardware modes: On
Redraw scene when viewports are exposed: On
Graphics level being used: OpenGL 4.6 (primary GPU’s maximum)

Anti-alias mode: 4x
Mip Map Filtering: Linear
Anisotropic Filtering Mode: High

Vendor Name: NVIDIA Corporation
Render version: 4.6
Shading Language: 4.60 NVIDIA
Driver Date: 3-6-2024
Driver Version: 31.0.15.3847
Maximum Texture size: 32768 x 32768
Z-Buffer depth: 24 bits
Maximum Viewport size: 32768 x 32768
Total Video Memory: 4 GB

Rhino plugins that do not ship with Rhino

Rhino plugins that ship with Rhino
C:\Program Files\Rhino 8\Plug-ins\Commands.rhp “Commands” 8.10.24228.13001
C:\Program Files\Rhino 8\Plug-ins\rdk.rhp “Renderer Development Kit”
C:\Program Files\Rhino 8\Plug-ins\RhinoRenderCycles.rhp “Rhino Render” 8.10.24228.13001
C:\Program Files\Rhino 8\Plug-ins\rdk_etoui.rhp “RDK_EtoUI” 8.10.24228.13001
C:\Program Files\Rhino 8\Plug-ins\NamedSnapshots.rhp “Snapshots”
C:\Program Files\Rhino 8\Plug-ins\MeshCommands.rhp “MeshCommands” 8.10.24228.13001
C:\Program Files\Rhino 8\Plug-ins\IronPython\RhinoDLR_Python.rhp “IronPython” 8.10.24228.13001
C:\Program Files\Rhino 8\Plug-ins\RhinoCycles.rhp “RhinoCycles” 8.10.24228.13001
C:\Program Files\Rhino 8\Plug-ins\Grasshopper\GrasshopperPlugin.rhp “Grasshopper” 8.10.24228.13001
C:\Program Files\Rhino 8\Plug-ins\Toolbars\Toolbars.rhp “Toolbars” 8.10.24228.13001
C:\Program Files\Rhino 8\Plug-ins\3dxrhino.rhp “3Dconnexion 3D Mouse”
C:\Program Files\Rhino 8\Plug-ins\Displacement.rhp “Displacement”
C:\Program Files\Rhino 8\Plug-ins\SectionTools.rhp “SectionTools”

Sorry, but this is no bug. You basically trigger a recomputation of the solution in such a short interval, that Grasshopper simply can’t handle it. It is not a high-performance system at all, and since Gh is entirely running on the UI thread (for very good reasons), you block the UI. There are ways to handle short intervals, you then need to bypass GH to a great portion and code your critical computation directly within a script. Without more information on your use-case, there is no way we can help…

Well the behavior is totally different from my experience using Timer/Trigger with <10ms interval in Rhino 5, 6, and 7. Also my coworker’s computers do not have the same issues. And after the weekend, leaving my computer shut down for a while, it appears the issue has resolved itself. So I think we will have to agree to disagree about it not being a bug, either gh/rhino, windows, or otherwise.

Other than that, you can use the System.Timers.Timer class in either C# or IronPython to set up a timer by code. I think the performance drop depends on various things, and everything counts in, from OS level, to hardware, other processes, and the actual computation. Since the script editor in Rh8 changed, simply the new implementation could more costly now.

In any case, you get very similar behaviour if your system runs either too fast or too slow. In discrete real-time systems usually a simulation step will drop the computation if you pass the duration of a step, which causes weird side-effects, but at least its not blocking anything. Again Grasshopper is really not suited for this sort of work, and its hard to code it reliable. The systems performance could suddenly drop, just because Windows install a update or similar. I think an almost realistic rate for GUI based apps would be 30hz or 33ms to update something to look as it is updated frequently. But then your downstream logic has to be optimised very well.