如何在PyQt5中停止一个线程

huangapple go评论71阅读模式
英文:

How to Stop a thread in PyQt5

问题

我尝试搜索解决我的问题的方法,但似乎找不到正确的方法来停止它,而不使GUI显示“未响应”。

基本上,这是我如何启动和停止它的方式:

def startTheThread(self):
    self.check_elements()
    # 创建新线程。目标函数是'myThread',这是我们一开始创建的函数。

    _email = str(self.lineEdit.text())
    _password = str(self.lineEdit_2.text())
    captcha_api = str(self.lineEdit_5.text())
    print(betburg_email)
    print(betburg_password)
    print(captcha_api)
    print(mode)

    self.t = threading.Thread(name='myThread', target=myThread, args=(self.theCallbackFunc, _email, _password, captcha_api))
    self.t.start()

def stop_client(self):
    self.check_elements()
    self.t.join()

def theCallbackFunc(self, msg):
    print('线程已向GUI发送此消息:')
    print(msg)
    print('---------')

class Communicate(QtCore.QObject):
    myGUI_signal = QtCore.pyqtSignal(str)

def myThread(callbackFunc, betburg_email, betburg_password, captcha_api):
    # 设置信号槽机制。
    mySrc = Communicate()
    mySrc.myGUI_signal.connect(callbackFunc)

    # 无限循环。通常希望线程一直运行。
    while(True):
        # 在这里执行有用的操作。
        client_run(betburg_email, betburg_password, captcha_api)

        msgForGui = '线程正在运行...'
        mySrc.myGUI_signal.emit(msgForGui)

我尝试启动另一个线程来处理关闭,但也不起作用。我使用了threading.Threading(),并尝试了Stack Overflow 上提供的各种方法,但.join() 是唯一被允许的版本。但是当与stop_client() 相连接的按钮被点击时,这会导致GUI冻结。

英文:

I tried searching for solutions to my problem but I cant seem to find the right way, to stop it without the GUI getting a "not responding"

Basically heres how im starting and stopping it:

    def startTheThread(self):
        self.check_elements()
        # Create the new thread. The target function is 'myThread'. The
        # function we created in the beginning.




        _email = str(self.lineEdit.text())
        _password = str(self.lineEdit_2.text())
        captcha_api = str(self.lineEdit_5.text())
        print(betburg_email)
        print(betburg_password)
        print(captcha_api)
        print(mode)
        

        self.t = threading.Thread(name = 'myThread', target = myThread, args = (self.theCallbackFunc, _email, _password, captcha_api))
        self.t.start()



        
    def stop_client(self):
        self.check_elements()

        self.t.join()








 def theCallbackFunc(self, msg):
        print('the thread has sent this message to the GUI:')
        print(msg)
        print('---------')


class Communicate(QtCore.QObject):
    myGUI_signal = QtCore.pyqtSignal(str)



def myThread(callbackFunc, betburg_email, betburg_password, captcha_api):
    # Setup the signal-slot mechanism.
    mySrc = Communicate()
    mySrc.myGUI_signal.connect(callbackFunc) 

    # Endless loop. You typically want the thread
    # to run forever.
    while(True):
        # Do something useful here.
        client_run(betburg_email, betburg_password, captcha_api)

        msgForGui = 'Thread running...'
        mySrc.myGUI_signal.emit(msgForGui)

I tried starting another thread to handle the closing but also doesnt work. im using threading.Threading() and i tried whats available on SO, and .join() is the only allowed version. but this makes the GUI freeze when the button that is connected to stop_client() is clicked

答案1

得分: 1

我强烈建议使用QThreads与PyQt5一起使用。它们的额外优点是可以被终止。而且可以更好地与PyQt的信号和槽系统一起使用。

然而,如果要使用常规的线程模块,可以对其进行子类化并添加一个可切换的标志,当线程运行时检查该标志并在更改时停止线程。这是一个非常基本的事件循环。

import time
import threading

class MyThread(threading.Thread):
    def __init__(self, *args, **kwargs):
        super(MyThread, self).__init__(*args, **kwargs)
        self.terminate = False

    def run(self):  # 这个需要是函数名!在这里执行你的操作
        while not self.terminate:
            print('Do Stuff, state is', self.terminate)
            time.sleep(1)  # 只要“做事情”的速度很快,它每秒检查一次

if __name__ == '__main__':
    t = MyThread()
    t.start() # 注意,我们使用.start(),但在.run方法中定义了它的功能。
    time.sleep(5)
    t.terminate = True

使用这段代码,你的代码理想情况下应该在将terminate设置为True后的最多一秒钟内停止。如果client_run()停止了代码执行,那么可能会出现问题。如果需要,你还可以在运行过程中在类初始化中存储用户名和密码。

英文:

I really suggest going over to QThreads for use with PyQt5. They have the added advantage of being able to be killed. As well as being able to work with PyQts signal and slot system a bit more nicely.

However, for using the regular threading module, you can subclass it and add a flag to toggle, that is checked when the thread is running and causes it to stop when changed. A very basic event loop.

import time
import threading


class MyThread(threading.Thread):
    def __init__(self, *args, **kwargs):
        super(MyThread, self).__init__(*args, **kwargs)
        self.terminate = False

    def run(self):  # This needs to the function name! Do your thing in this
        while not self.terminate:
            print('Do Stuff, state is ', self.terminate)
            time.sleep(1)  # As long as the "Do stuff" happens fast, it checks every one second


if __name__ == '__main__':
    t = MyThread()
    t.start() # Note, we use .start() but define what it does in the .run method. 
    time.sleep(5)
    t.terminate = True

Using this code, your code will ideally stop at most one second after setting terminate to True. If client_run() stops code execution, then you might get a hitch however.
You can also store username, password in the class init if needed in during the run.

huangapple
  • 本文由 发表于 2020年1月3日 16:47:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/59575497.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定