2

我为键盘记录器创建了一个线程,该线程与另一个产生一些声音的线程并行记录(我想捕捉反应时间)。

不幸的是,尽管我调用了 killKey() 并且打印了“invoked killkey()”,但线程从未完成。

我总是从这个线程中得到一个 thread.isActive() = true 。

class KeyHandler(threading.Thread):
    hm = pyHook.HookManager()

    def __init__(self): 
       threading.Thread.__init__(self) 

    def OnKeyboardCharEvent(self,event):
        print 'Key:', event.Key
        if event.Key=='E':
            ...   
        return True

    def killKey(self):
        KeyHandler.hm.UnhookKeyboard() 
        ctypes.windll.user32.PostQuitMessage(0) 
        print "invoked killkey()"

    def run(self):
        print "keyHandlerstartetrunning"
        KeyHandler.hm.KeyDown = self.OnKeyboardCharEvent
        KeyHandler.hm.HookKeyboard()
        #print "keyboardhooked"
        pythoncom.PumpMessages()

更准确地说, ctypes.windll.user32.PostQuitMessage(0) 什么都不做

我倾向于在这个线程中调用 killKey() 和相应的 ctypes.windll.user32.PostQuitMessage(0) 的外部超时。

4

2 回答 2

2

PostQuitMessage 必须从同一个线程发布。为此,您需要引入一个全局变量STOP_KEY_HANDLER。如果你想退出,那么只需STOP_KEY_HANDLER = True从你想要的任何线程设置全局,它会在下一次击键时退出。您的密钥处理程序必须在主线程上运行。

STOP_KEY_HANDLER = False

def main():
    pass # here do all you want
    #bla bla
    global STOP_KEY_HANDLER
    STOP_KEY_HANDLER = True # This will kill KeyHandler


class KeyHandler:
    hm = pyHook.HookManager()

    def OnKeyboardCharEvent(self,event):
        if STOP_KEY_HANDLER:
            self.killKey()
        print 'Key:', event.Key
        if event.Key=='E':
            pass
        return True

    def killKey(self):
        global STOP_KEY_HANDLER
        if not STOP_KEY_HANDLER:
            STOP_KEY_HANDLER = True
            return None
        KeyHandler.hm.UnhookKeyboard()
        ctypes.windll.user32.PostQuitMessage(0)
        print "invoked killkey()"

    def _timeout(self):
        if self.timeout:
            time.sleep(self.timeout)
            self.killKey()

    def run(self, timeout=False):
        print "keyHandlerstartetrunning"
        self.timeout = timeout
        threading.Thread(target=self._timeout).start()

        KeyHandler.hm.KeyDown = self.OnKeyboardCharEvent
        KeyHandler.hm.HookKeyboard()
        #print "keyboardhooked"
        pythoncom.PumpMessages()


k=KeyHandler()

threading.Thread(target=main).start()
k.run(timeout=100) # You can specify the timeout in seconds or you can kill it directly by setting STOP_KEY_HANDLER to True.
于 2014-05-07T12:44:53.137 回答
1

我猜pbackup的解决方案很好。总结一下,我通过自己发送密钥而不是等待用户输入找到了解决方案。它可能不是最好的,但在我的计时线程中与其他计时例程并行是最快的。

    STOP_KEY_HANDLER = True

    # send key to kill handler - not pretty but works
    for hwnd in get_hwnds_for_pid (GUIWINDOW_to_send_key_to.pid):
        win32gui.PostMessage (hwnd, win32con.WM_KEYDOWN, win32con.VK_F5, 0)
    # sleep to make sure processing is done
    time.sleep(0.1)

    # kill window
    finished()
于 2014-05-07T14:50:07.037 回答