Python启动函数作为线程不会加入/结束

时间:2017-02-24 21:36:56

标签: python multithreading thread-safety python-multithreading

我目前遇到线程加入问题。我有一个函数,根据给定的参数执行一组操作。有一个“启动”按钮,它将启动该功能,该功能作为一个线程运行。

相同的按钮变成“停止”按钮,单击时将停止该功能。不幸的是,线程似乎没有结束。

相关代码在这里......注意“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方法:

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

1 个答案:

答案 0 :(得分:0)

您不得在线程中使用大多数wx次调用。必须仅从主线程调用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处理它。您可能无法以图形方式看到差异,但您的线程将正确退出。