How to escape from script stably and reliably

Hi guys, I was trying to use ESC key to break a loop, and found out 2 ways to use ESC key.
One is scriptcontext.escape_test(False), Another is use OnEscapeKeyPressed as a event handler. But after test, both of them require couple of times of pressing ESC to break loop.

How can I make ESC more accurately and stably like those original rhino commands? The attachments are test code I found.
esc test with OnEscapeKeyPressed.py (991 Bytes)
esc test with scriptcontext.escape_test.py (258 Bytes)

Alternatively can I use third party libraries like pynput to monitor mouse and keyboard?

I think third party libraries will make some trouble if I distribute my script to others who don`t have them, am I correct? Is there any other way to solve this problem conveniently(like auto install libraries when installing my script)?

Many thanks

I’m worried that there is no good solution.

The default mechanism in .Net (C#, IronPython) is using a CancellationToken. You can create your heavy computation in another task and provide one.

Still if your task is busy, you will have issues to cancel it properly, so you may need to terminate it by force, risking to crash the application. In any case, you can approach this problem also a bit differently. You guard for infinite or long loops, you measure or pre-compute computation time and terminate after a time-out or you properly check your geometry before you do some heavy computation with it. You can also use volatile flags, but I bet the problem comes from the Rhino kernel. Usually you get this by doing some sort of heavy computation (e.g. Boolean Difference) . In that case its not directly in your control.

1 Like

on windows you could try this

import ctypes

def escape_pressed():
    return ctypes.windll.user32.GetAsyncKeyState(0x1B)&0x8000

def TimeConsumingTask():    
    for i in range(10000):
        if escape_pressed():
            print 'escaped'
            break
        else:
            print i

TimeConsumingTask()
1 Like

Jdhill,thank you very much for the solution, it’s perfect, much more easier to use and opens more ways to use keyboard and mouse button other than Rhino native event.

Btw, do you know any API on Mac that is similar to winuser? I did some research. And found out that Cocoa is the probable answer, but it looks much harder to apply when compared with winuser.

sorry, but I don’t happen to know how to do that on mac

1 Like

It’s alright, thank you all the same. Ctypes is already good enough for me

Is this such a good solution? Because the moment you check for the key being pressed, the user has to press it. This works great if the iteration duration is small, but now consider you are stuck on some longer lasting call… Pressing a key has no effect then at all. Using an event handler in conjunction with a volatile bool or with a cancellation token will ensure the user has to press it only once.

1 Like

Thank you for noticing, Tom.

Actually I’m quit new on coding, not so familiar with many stuff, especially on the aspects of Rhino event handler as well as display conduit. And I didnt find any tutorials to learn systematically, only some samples or words fragmentally explain how they work. I tried to understand them but I think I’ll need more detailed tutorial, do you know anywhere to find good tutorials?

Back to my quistion, I think for me, for small loops, Ctypes is easy and direct enough, for more complex loop, I learnt to use Rhino.Input.GetResult to break, I think it’s a native and stable way, but it won’t let user input other keyboard button to control.