Grasshopper

algorithmic modeling for Rhino

Hi,

I'm trying to write a component which has a background thread, a timer, that will move a point in a circular path in the Rhino Document every 100ms while the component itself won't get stuck and also will respond to parameters changes in it's SolveInstance function.

I've been using Rhino.RhinoDoc.ActiveDoc's AddPoint function in the background thread.

The problem is that Rhino always crashes when i touch the view while the background timer moving the point.

The background thread does the following algorithm:

- my_active_doc.AddPoint(circle_points[i])

- my_active_doc.Sleep(100ms)

- my_active_doc.PurgePoint(circle_points[i])

- i += 1

- my_active_doc.Views.Redraw()

I've placed my_active_doc with RhinoDoc.ActiveDoc only once in the component class constructor (i did it because there's a warning in the ActiveDoc documentation that says you either use the given DocObject which refers to written Rhino Plugins or use only the first instance you get from ActiveDoc)

I even tried locking with a static locker object each call to the my_active_doc and that did not help.

I'd like to hear any suggestions, maybe i'm using it wrong and that's not the way to change the active rhino document in the background.

Now i know it IS possible because i've seen many GrassHopper components that simulate a motion of an object while the grasshopper component is still responsive and there isn't output parameter - so they're probably not using ExpireSolution every 100ms

Thanks,

H.

Views: 789

Replies to This Discussion

Much safer would be to use gh timer component instead of system.timer. 

The gh timer component expires the solution with the given iterval.

To draw something without the output parameter you have to read more about drawviewportwires and drawviewportmeshes

You cannot do anything which affects the UI from any thread other than the main application thread. Never. Ever. Instant Crash.

Here are your solutions:

  1. Use a System.Threading.Timer, but don't execute any code from there. Instead, invoke a method on the main Rhino ui thread which does the point addition/redrawing.
  2. Use a System.Windows.Forms.Timer, which runs on the main thread to begin with. Problem here is you may have to put the timer on a form for it to work well.
  3. Use a Grasshopper timer object (as Mateusz suggested).
  4. Use the ScheduleSolution method on GH_Document to trigger a new solution x milliseconds in the future.
  5. Use the ScheduleRedraw method on GH_Canvas to trigger a new redraw x milliseconds in the future.

I'm not sure which of these suits your needs the best, though I suspect it's #1.

Another thing to keep in mind is that timers that run on different threads can start to raise overlapping events. If it somehow takes longer than 100ms to execute your iteration (for example because something else that is computationally expensive is already happening) then you start to collect timer events faster than you can handle them. Ideally you'd disable/suspend the timer once you get an tick event, then restart the timer when you're done doing whatever it is you're doing.

--

David Rutten

david@mcneel.com

Hi,

Thanks for the quick reply :)

I just tried using System.Windows.Form.Timer that seemed to work very good, though i'll give it some more heavy testing.

I'm wondering about the #1 solution you suggested - How can i invoke a method on the main UI thread?

Thanks!

RhinoWindow.Invoke() is probably the best option. If the Grasshopper window is always loaded while your code runs, then you can also use the Invoke methods on Grasshopper.Instances.DocumentEditor.

--

David Rutten

david@mcneel.com

Alright, I'll give it a try too.

 Once again, informative and quick reply, Thanks a lot David i really appreciate your help

RSS

About

Translate

Search

Videos

  • Add Videos
  • View All

© 2024   Created by Scott Davidson.   Powered by

Badges  |  Report an Issue  |  Terms of Service