1

現在、スレッド結合に問題があります。私は与えられたパラメータに応じて操作のセットリストを行う関数を持っています。この機能を開始する「開始」ボタンがあり、この機能はスレッドとして実行されます。スレッドとしてのPythonの開始関数は、結合/終了しません。

同じボタンをクリックすると機能を停止する「停止」ボタンに変わります。残念ながら、スレッドは終了していないようです。

関連するコードはここにある...

すべてのコメントは素晴らしいことだ...「self.stop_com_loop」は、スレッドを終了するために使用されることに注意してください。

def Start_Com(self): 
    """ 
    Start Com Funtion 
    """ 
    self.AppendText("\n-----------------Start Communication to Modbus-----------------\n") 

    self.stop_com_loop = False 

    cmd = ("modpoll.exe -p 504 -1 192.168.1.100") 

    self.AppendText("Executing Command: %s" %(cmd)) 

    while(not self.stop_com_loop): 
     self._runcommand(cmd) 

     time.sleep(1) 

    self.logging_cb.Enable(True) 
    self.ping_btn.Enable(True) 
    self.com_btn.SetLabel(START_COM_STR) 

    self.AppendText("\n-----------------End Communication to Modbus-----------------\n") 

    print("Why Won't I die?") 

def _com_evt(self, 
      evt): 
    """ 
    Com Button Event 
    """ 
    if self.com_btn.GetLabelText() == START_COM_STR: 
     self.logging_cb.Enable(False) 
     self.ping_btn.Enable(False) 
     self.com_btn.SetLabel(STOP_COM_STR) 

     self.com_thread = threading.Thread(target=self.Start_Com) 
     self.com_thread.daemon = True 
     self.com_thread.start() 

    elif self.com_btn.GetLabelText() == STOP_COM_STR: 
     self.stop_com_loop = True 
     # self.com_thread.join() # When this line is inserted. System Hangs 
     while(True): 
      print self.com_thread 
      print self.com_thread.isAlive() 
      if not self.com_thread.isAlive(): 
       break 
      time.sleep(1) 
     self.com_btn.SetLabel(START_COM_STR) 
    else: 
     self.AppendText("Unknown Start Com Button State") 

def _runcommand(self, 
       cmd): 
    """ 
    Run Command given and output to text control 
    """ 

    self.error_occured = False 

    cmd_l = cmd.split(" ") 

    self.pjob = subprocess.Popen(cmd, 
           stdout=subprocess.PIPE, 
           stderr=subprocess.STDOUT, 
           stdin=subprocess.PIPE, 
           bufsize=0, 
           creationflags = subprocess.CREATE_NEW_PROCESS_GROUP) 

    while True: 
     line = self.pjob.stdout.readline() 

     skip_line = False 

     for token in self.DO_NOT_PRINT_TOKEN_L: 
      if ((token in line)): 
       skip_line = True 
     if skip_line: 
      continue 

     wx.Yield() 

     if line.strip() == "": 
      pass 
     elif self.ERROR_COM_TOKEN in line: 
      self.error_occured = True 
      self.AppendText("%-30s~ ERROR: %s\n" %(self.GetTime(), 
                 line.strip())) 
     else: 
      self.AppendText("%-30s~ %s" %(self.GetTime(), 
              line.strip())) 

     if not line: break 

    # Print that error occured and when error resolves 
    if self.error_occured: 
     self.AppendText("\nXXXXXXXXXXXXXXXXXXXXX %% ERROR OCCURED %% XXXXXXXXXXXXXXXXXXXXX\n") 
     self.last_one_was_error = True 
     self.AppendOverviewText("%-30s~ %% ERROR OCCURED %% " 
      %(self.GetTime())) 
    else: 
     if self.last_one_was_error: 
      self.AppendText("\n+++++++++++++++++++++ ** ERROR RESOLVED ** +++++++++++++++++++++\n") 
      self.AppendOverviewText("%-30s~ ** ERROR RESOLVED ** " 
       %(self.GetTime())) 
     self.last_one_was_error = False 

    self.pjob.wait() 
    self.pjob = None 

編集:私は入社からスレッドを停止するようだラインに分離しました ...のappendText機能は、加入からスレッドを停止するようです。なぜ私は考えていない。

logging_ctrl

self.logging_ctrl = wx.TextCtrl(self, -1, "", 
           style=wx.TE_MULTILINE | wx.TE_READONLY) 

のappendTextメソッドの初期化:あなたがスレッドで最もwx呼び出しを使用してはならない

def AppendText(self, 
       text): 
    """ 
    Append text to logging text control and file is logging is enabled 
    """ 
    self.logging_ctrl.AppendText(str(text) + '\n') 
+0

あなたの質問に「参加」がありますが、 'self.stop_com_loop = True'を設定した直後に' self.com_thread.join() 'を実際に呼び出す必要があります –

+0

@ Jean-FrançoisFabreありがとう、 joinはシステムをハングします。 IsAlive()メソッドを削除して使用して終了したかどうかを確認し、終了していないかどうかを確認します。私はコメントを付けて戻しました。 – Sam

+0

私は考えているかもしれませんが、 '_runco​​mmand'のコードを表示する必要があります。 –

答えて

0

wxグラフィカルルーチンはメインスレッドからのみ呼び出されなければなりません。

回避策として、スレッドからアクションを登録することを許可する安全なwx.CallAfter()メソッドがあります。あなたのAppendText方法で

は、ただやる:あなたがメインスレッドにしている場合は

def AppendText(self, 
       text): 
    """ 
    Append text to logging text control and file is logging is enabled 
    """ 
    wx.CallAfter(self.logging_ctrl.AppendText,str(text) + '\n') 

は、それは前と同じことをするでしょう。他のスレッドでは、実行するアクションを書き留めるだけでロックアップを回避し、wx mainloopはそれを処理します。違いをグラフィカルに見ることはできませんが、スレッドは正常に終了します。

+0

ありがとうwx.CallAfter()を使用していますか?今のようにwxとスレッドを使用してはいけませんか? – Sam

+0

'wx.CallAfter'はこのようなスレッドの場合は_made_です。私たちのアプリはいつも問題なく(クラッシュする前に) –

関連する問題