Event handler issues [SOLVED]


#1

Hi,

I am experiencing an issue around events. You may be able to help me here.

I am trying to use Rhino as just modeling tool, and have GH to get all the info of the scene so I can save it later into DB through Server.

I am building everything around PYTHON and STICKY dictionary in GH env.

I have register some event handlers in order to maintain updated the info in the sticky dictionary. It was suggested in some other topic to have flags behind the events to control properly how these are working, and then to take actions when the application is in Idle status.
This, so far, is working fine.

My problem comes when I perform an action in all the geometric structure which has lets say 20K objects. Performance is really slow in the
event handling part, not in the Rhino.RhinoApp.Idle process which has all the logic.

I have unregistered the event handlers just to see the problem, but even if I verify the ‘flags logic’ is not being running, therefore the idle process will take no actions, still moving all the geometry or deleting it is too slow. We are talking here about 5 minutes, when performing those actions without subscriving event handlers at the beginning can take 1 or 2 seconds.

Any idea what could be going on?

Regards


(Giulio Piacentino) #2

Hi Aitor

event handlers are VERY tricky to deal with from Grasshopper and vanilla GhPython for V5. This is because every time the solution runs, the code is evaluated again (remember, Python is basically always assumed to be evaluated) and the definitions of functions are re-created.

You therefore need to be careful, that once a function has registered, it does not register again for the same event handler. You could try adding a reference to System.Windows.Forms.MessageBox.Show() and show a dialog, so that you can debug how many times the function runs. What I did in sample code dealing with this problem, was to also store a reference to the interpreted function, so that if I wanted to remove it from the event handler at a later moment, I could get the “old version” from the dictionary.

GhPython in V6 has a new GH-SDK method that does not reinterprets the whole code, but just the RunScript() method, and therefore allows this type of operations to be written more easily.

Does it make sense?

Giulio


Giulio Piacentino
for Robert McNeel & Associates
giulio@mcneel.com


#3

Hi Giulio,

I am using flags to avoid the issue you are mentioning. I am sure the events are not being registered several times. Also when I unregister these events, so idle process does nothing cause all flags are down still is slow. Here example of code making the application slow.


(Giulio Piacentino) #4

I cannot test by rewriting all this, I am sure you understand.
I also do not see any -=, so I do not think you are un-registering from these events.

If you are trying to make a working system that recognizes every Rhino command from a GhPython script, I think you are on a path of pain. This would be the work of a very advanced plug-in, where possibly you’d have also debugging working. Also, because events are strongly-typed, this is probably a better endeavor in a C# plug-in.


#6

Morning Giulio,
I understand it can be a bit more clomplex than other topics. ‘-=’ I am doing it, just havent copied it in the discussion.
Thanks for your time, when I have the time, I will double check creating C# plug-in. Just playing a bit around the application and decided to do first scripts as python components, not even .PY files.


#7

@Aitor,

i guess this line could be a first source for your slowdown:

if e.ObjectId not in sc.sticky["eventHandlerFlags"].keys()

You’re collecting the object ids and the event types for every id, but you’re checking if they are in the sticky with every run of your InitializeKey(e) function. The sticky dictionary is not really fast and checking for entries also slows down things the more you fill it up. You’re also creating a copy of the whole dictionary here using .keys()

Have you considered creating a list, or if you want to avoid duplicates and need no order, a set holding tuples of the id and the event type instead of the sticky ? This list or set might then be processed in your idle event and cleared once done. I would recommend to use a global variable for it so all events can fully access it. Also i would recommend to exit all events as early as possible, eg. check in your idle event if the list or set is empty, then exit immediately.

To check how often the event gets fired, you might just print using counters. The idle event fires very often. I have a script which checks in the idle event if it has been run in the same second, if so it exits in the first line.

The sticky i would use only to store references to the events you register, so you can unregister them.

_
c.


#8

Thumbs Up Clement!!

I should be using has_key function instead of getting keys and checking if the key is in the list. My bad :P.

Thanks.