Python PySide6中GUI冻结

3

我正在开发一款软件,其中涉及到调用API获取数据。然而,每当我调用API获取数据时,GUI界面就会冻结。起初我认为是线程问题,于是将函数转移到了线程中,但问题在于一旦使用join()函数,应用程序又会再次冻结。 现在,我希望能够在函数的同一个位置等待线程结束,然后从该函数的同一个位置继续执行下去。请问在Python中是否有实现这种功能的方法?

threads = []
def call_api(self, query, index, return_dict):
    thread = threading.Thread( target=self.get_data, args=(query, index, return_dict)) 
    self.threads.append(thread)
    thread.start()

def get_all_tickets(self, platform):
    if platform == 'All':

    self.call_api(query1, 0, return_dict)
    self.call_api(query2, 1, return_dict)

    for thread in self.threads:
         thread.join()
     # The app freezes here
     # Is there a way to wait at this point asynchronously until the processes are complete 
    and continue from that point without the GUI freezing?

1
看起来你正在混合使用多进程和线程,为什么? - paisanco
使用join使得像这样使用线程没有意义,因此您应该使用带有自定义信号的QThread。正如已经指出的那样,您正在尝试做什么还不清楚,而且您的代码也不足够。 - musicamante
首先非常感谢您的快速回复,我放了一部分代码只是为了展示我遇到的问题,我能否得到使用获取函数并在线程完成时报告的QThread示例? - David_F
删除 join() 并使用其他方法来检查是否获取到数据 - 您可以使用全局变量(或队列)并使用 timer 定期执行函数,以检查您在全局变量(或队列)中拥有什么。或者使用 PyQt QThread,在获取所有数据时可能会有更好的执行此部分的方法。 - furas
嗨@furas,如果您能上传一个使用QThread描述我的情况的示例,我会很高兴。 - David_F
1个回答

2

一个可能的选择是使用 QThreadfinished 信号,你可以将其连接到一个包含你的 get_all_tickets 方法中剩余逻辑的槽中。

threads = []
def call_api(self, query, index, return_dict):
    thread = QThread() 
    worker = Worker(query, index, return_dict)
    worker.moveToThread(thread)
    thread.started.connect(worker.run)
    worker.finished.connect(thread.terminate)
    thread.finished.connect(self.continue_getting_all_tickets)    
    self.threads.append(thread)
    thread.start()

def get_all_tickets(self, platform):
    if platform == 'All':
        self.call_api(query1, 0, return_dict)
        self.call_api(query2, 1, return_dict)

def continue_getting_all_tickets(self):
    # this will be called once for each and every thread created
    # if you only want it to run once all the threads have completed 
    # you could do something like this:
    if all([thread.isFinished() for thread in self.threads]):
        # ... do something
    

工作者类可能是这样的。

class Worker(QObject):
    finished = Signal()
    def __init__(self, query, index, return_dict):
        super().__init__()
        self.query = query
        self.index = index
        self.return_dict = return_dict

    def run(self):
        # this is where you would put `get_data` code
        # once it is finished it should emit the finished signal
        self.finished.emit()      

希望这能帮助你找到正确的方向。

嗨 @alexpdev ,我在你的回答下附上了一篇帖子,谢谢。 - David_F
谢谢您的回复 @alexpdev,您可以帮我找到QThread应该获取的类吗? - David_F
@David_F 请查看更详细的答案。如果您仍需要帮助,则需要包含更多的代码。 - Alexander
非常感谢您的帮助。我添加了另一个函数来检查线程的状态,并修复了您建议的以下代码: 你: if all([thread.isFinished() for thread in self.threads]): 我: if all([not thread.is_alive() for thread in self.threads]): - David_F

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接