2017-08-12 12 views
2

私はスレッドクラスを持っていて、私のメイン関数で何度もスレッドを開始/停止したいと思っています。私はthis linkthis methodを使って私の問題を解決しました。ここでは、コンソールでキーストロークを出力する簡単なスレッドである:私はときthr.stop()を呼び出し、それがwhileループ終了し、いくつかのキーストロークを押ししようとすると、スレッドがすでに停止しているようですが、ときPythonでスレッディングするループを制御する

global isWindows 

isWindows = False 


try: 
    from win32api import STD_INPUT_HANDLE 
    from win32console import GetStdHandle, KEY_EVENT, ENABLE_ECHO_INPUT, ENABLE_LINE_INPUT, ENABLE_PROCESSED_INPUT 
    import win32gui 
    import threading 
    from time import sleep 
    import sys 
    isWindows = True 
except ImportError as e: 
    import sys 
    import select 
    import termios 


class KeyPoller(threading.Thread): 

    def __init__(self): 
     super(KeyPoller, self).__init__() 
     #threading.Thread.__init__(self) 
     self.stop_event = threading.Event() 
     global isWindows 
     if isWindows: 
      self.readHandle = GetStdHandle(STD_INPUT_HANDLE) 
      self.readHandle.SetConsoleMode(ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT) 

      self.curEventLength = 0 
      self.curKeysLength = 0 

      self.capturedChars = [] 
     else: 
      # Save the terminal settings 
      self.fd = sys.stdin.fileno() 
      self.new_term = termios.tcgetattr(self.fd) 
      self.old_term = termios.tcgetattr(self.fd) 

      # New terminal setting unbuffered 
      self.new_term[3] = (self.new_term[3] & ~termios.ICANON & ~termios.ECHO) 
      termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.new_term) 

    def poll(self): 
     if isWindows: 
      if not len(self.capturedChars) == 0: 
       return self.capturedChars.pop(0) 

      eventsPeek = self.readHandle.PeekConsoleInput(10000) 

      if len(eventsPeek) == 0: 
       return None 

      if not len(eventsPeek) == self.curEventLength: 
       for curEvent in eventsPeek[self.curEventLength:]: 
        if curEvent.EventType == KEY_EVENT: 
         if ord(curEvent.Char) == 0 or not curEvent.KeyDown: 
          pass 
         else: 
          curChar = str(curEvent.Char) 
          self.capturedChars.append(curChar) 
       self.curEventLength = len(eventsPeek) 

      if not len(self.capturedChars) == 0: 
       return self.capturedChars.pop(0) 
      else: 
       return None 
     else: 
      dr,dw,de = select.select([sys.stdin], [], [], 0) 
      if not dr == []: 
       return sys.stdin.read(1) 
      return None 

    def stop(self): 
     print("stopping the thread") 
     self.stop_event.set() 

    def stopped(self): 
     return self.stop_event.is_set() 

    def run(self): 
     while not self.stopped(): 
      c=self.poll() 
      if not c is None: 
       print(c) 

if __name__=='__main__': 

    thr=KeyPoller() 
    print("starting the thread #1") 
    thr.start() 
    sleep(5) 
    print("stopping the thread #1") 
    # sadly if you press any key in this time it would be saved and printed after thr2.start 
    thr.stop() 
    thr.join() 
    sleep(5) 
    thr2=KeyPoller() 
    print("starting the thread #2") 
    thr2.start() 
    sleep(5) 
    print("stopping the thread #2") 
    thr2.stop() 
    print("Exiting the whole program") 

私の問題はあるがI thr2.start()を呼び出すと、私のスレッドの最初のインスタンスから古いキーストロークが表示され、停止機能を呼び出すかどうかに関わらず、すべてのキーストロークがまだ残っているようです。

答えて

1

私の見解から、インスタンス変数としてtreading.event()を初期化する感覚はありません。イベントはスレッド/プロセス同期のためのもので、インスタンス内でこれを宣言すると他のインスタンスでは見られません。

あなたのコードでは、私はstop_eventにブール変数を使用します。これはLinux環境で私のために働く。

class KeyPoller(threading.Thread): 

    def __init__(self): 
     super(KeyPoller, self).__init__() 
     #threading.Thread.__init__(self) 
     self.stop_event = False 
     global isWindows 
     if isWindows: 
      self.readHandle = GetStdHandle(STD_INPUT_HANDLE) 
      self.readHandle.SetConsoleMode(ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT) 

      self.curEventLength = 0 
      self.curKeysLength = 0 

      self.capturedChars = [] 
     else: 
      # Save the terminal settings 
      self.fd = sys.stdin.fileno() 
      self.new_term = termios.tcgetattr(self.fd) 
      self.old_term = termios.tcgetattr(self.fd) 

      # New terminal setting unbuffered 
      self.new_term[3] = (self.new_term[3] & ~termios.ICANON & ~termios.ECHO) 
      termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.new_term) 

    def poll(self): 
     if isWindows: 
      if not len(self.capturedChars) == 0: 
       return self.capturedChars.pop(0) 

      eventsPeek = self.readHandle.PeekConsoleInput(10000) 

      if len(eventsPeek) == 0: 
       return None 

      if not len(eventsPeek) == self.curEventLength: 
       for curEvent in eventsPeek[self.curEventLength:]: 
        if curEvent.EventType == KEY_EVENT: 
         if ord(curEvent.Char) == 0 or not curEvent.KeyDown: 
          pass 
         else: 
          curChar = str(curEvent.Char) 
          self.capturedChars.append(curChar) 
       self.curEventLength = len(eventsPeek) 

      if not len(self.capturedChars) == 0: 
       return self.capturedChars.pop(0) 
      else: 
       return None 
     else: 
      dr,dw,de = select.select([sys.stdin], [], [], 0) 
      if not dr == []: 
       return sys.stdin.read(1) 
      return None 

    def stop(self): 
     print("stopping the thread") 
     self.stop_event = True 

    def stopped(self): 
     return self.stop_event 

    def run(self): 
     while not self.stopped(): 
      c=self.poll() 
      if not c is None: 
       print(c) 
+0

チップをありがとう、私は窓を使用していますが、私は同じ問題に直面しています。 –

+0

あなたの答えはうまくいきませんでしたが、私は単純な関数で置き換えようとしました。ありがとう。 –

関連する問題