我有 Kivy 应用程序,屏幕上有一个下载按钮,可以下载和处理各种远程数据表。一切都工作得很好,但 gui 在该过程中被阻止,正如 MDSpinner 所证明的那样,该 MDSpinner 在下载过程完全完成之前冻结了大约一半。
整个深度学习进程正在另一个不接触 GUI 的线程中运行,因此这种情况不会发生。
我的故障排除发现 UrlRequest 回调正在执行阻塞。即使回调中的简单睡眠也会挂起 GUI!
知道为什么吗?我需要在另一个线程中运行回调吗?
由于实际代码非常复杂,这里有一些简单的伪代码来演示问题。
from kivy.network.urlrequest import UrlRequest
from functools import partial
from kivy.clock import Clock, mainthread
from threading import Thread
from kivymd.uix.screen import MDScreen
import time
class myScreen(MDScreen):
def on_button(self):
# activate spinner when download button pressed
self.ids.spinner.active = True
# run sync stuff in new thread
t = Thread(target=self.sync_thread)
t.start()
def sync_thread(self):
# lots of code here including several async downloads like this:
download(some_url)
# when all downloads are done, kill spinner
self.kill_spinner()
@mainthread
def kill_spinner(self):
# uses decorator to set gui widget from another thread
self.ids.spinner.active = False
# URLRequest code -----------------------------
def download(self, url):
cb = partial(mycallback, arg)
UrlRequest(url=url, req_headers=myconfig.headers, timeout=timeout, on_success=cb, on_error=cb, on_failure=cb)
def mycallback(self, arg):
# used to process data from each download
# PROBLEM LIES HERE! Anything here - even a simple sleep will hang spinner(gui) until finished
time.sleep(5)
我认为你应该在on_button函数中调用kill_spinner函数。在这里,即使您在这里有一个线程,您也会在下载并处理导致滞后的所有内容后禁用微调器。
from kivy.network.urlrequest import UrlRequest
from functools import partial
from kivy.clock import Clock, mainthread
from threading import Thread
from kivymd.uix.screen import MDScreen
import time
class myScreen(MDScreen):
def on_button(self):
# activate spinner when download button pressed
self.ids.spinner.active = True
# run sync stuff in new thread
t = Thread(target=self.sync_thread)
t.start()
# when all downloads are launched, kill spinner
self.kill_spinner()
def sync_thread(self):
# lots of code here including several async downloads like this:
download(some_url)
@mainthread # should be useless
def kill_spinner(self):
# uses decorator to set gui widget from another thread
self.ids.spinner.active = False
# URLRequest code -----------------------------
def download(self, url):
cb = partial(mycallback, arg)
UrlRequest(url=url, req_headers=myconfig.headers, timeout=timeout, on_success=cb, on_error=cb, on_failure=cb)
def mycallback(self, arg):
# used to process data from each download
# PROBLEM LIES HERE! Anything here - even a simple sleep will hang spinner(gui) until finished
time.sleep(5)