class SharedData(QtCore.QObject):
def __init__(self):
super(SharedData, self).__init__()
self.loader = None
self.mutex = QtCore.QMutex()
self.loader_created = QtCore.QWaitCondition()
class Bungie(QtCore.QObject):
denied = QtCore.Signal()
authenticated = QtCore.Signal()
def __init__(self, data):
super(Bungie, self).__init__()
self.data = data
self.bungie = bungie.Bungie()
@QtCore.Slot(str, str)
def login(self, username, password):
...
try:
self.bungie.login(username, password)
except bungie.InvalidCredentials:
...
self.denied.emit()
else:
self.authenticated.emit()
with util.Locker(self.data.mutex):
self.data.loader = loader.Loader(self.bungie)
self.data.loader_created.wakeAll()
...
class Loader(QtCore.QObject):
def __init__(self, data):
super(Loader, self).__init__()
self.data = data
@QtCore.Slot()
def start(self):
with util.Locker(self.data.mutex):
if self.data.loader is None:
self.data.loader_created.wait(self.data.mutex)
with util.Locker(self.data.mutex):
if self.data.loader:
self.data.loader.loadDefinitions()
class MainWidget(QtGui.QWidget):
login = QtCore.Signal(str, str)
def __init__(self, parent=None):
super(MainWidget, self).__init__(parent)
# UI
...
self.data = SharedData()
self.bungie_thread = QtCore.Thread(parent=self)
self.bungie = Bungie(self.data)
self.bungie.moveToThread(self.bungie_thread)
self.loader_thread = QtCore.Thread(parent=self)
self.loader = Loader(self.data)
self.loader.moveToThread(self.loader_thread)
self.login.connect(self.bungie.login)
self.loader_thread.started.connect(self.loader.start)
self.bungie_thread.start()
self.loader_thread.start()
以下是 loadDefinitions 的作用:
def loadDefinitions(self):
if self.item_def is None:
with open("manifest/DestinyInventoryItemDefinition_hashkey.json",
"r") as fin_json:
self.item_def = json.load(fin_json)
if self.bucket_def is None:
with open("manifest/DestinyInventoryBucketDefinition_hashkey.json",
"r") as fin_json:
self.bucket_def = json.load(fin_json)
if self.stat_def is None:
with open("manifest/DestinyStatDefinition_hashkey.json",
"r") as fin_json:
self.stat_def = json.load(fin_json)
所以我发生的事情是创建两个工作人员将一些数据传递给他们的构造函数并为每个工作者创建一个线程并将它们移动到各自的线程。一旦线程启动它就会启动加载器并等待。另一个线程将唤醒它,然后运行 loadDefinitions 。该问题似乎是 loadDefinitions 中的第一个 json.load()。它打开并反序列化一个~8.75MB的json文件。另外两个只有~9KB。在这期间,用户界面冻结了 - 我在这里缺少什么?为什么会这样?
感谢。
编辑:
如果我将 loadDefinitions 替换为:
numbers = []
for _ in xrange(1000000):
numbers.append(random.randint(1, 101))
UI不会阻止。问题似乎与 json.load
有关由于文件太大,我只是在显示UI之前选择加载它。