简体   繁体   English

改变PySide.QtGui.QListWidget与从multiprocessing.Pool异步调用发出信号导致运行时错误?

[英]Altering PySide.QtGui.QListWidget with an emitted signal from a multiprocessing.Pool async call results in Runtime Error?

I have: 我有:

from PySide.QtCore import Signal, QObject
from multiprocessing import Pool

def some_computation():
    pass
    # ..some computations
    return 'result'

class MyClass(QObject):

    my_signal = Signal()

    def __init__(self):
        self.mylistwidget = # ... QListWidget from somewhere

        # bind the signal to my slot
        self.my_signal.connect(self.on_my_signal)

    # this is called after computation thread is finished
    def my_callback_fct(result):
        # ..bla bla
        self.my_signal.emit()

    # this is the function I call
    def do_some_async_computation(self)
        pool = Pool(processes=2)
        pool.apply_async(target=some_computation, callback=my_callback_fct)

    # this is the slot
    def on_my_signal(self):
        self.mylistwidget.clear()

I read around stackoverflow that in order to change the gui from a secondary execution thread one must use slot-signal mechanism, which is what I did in MyClass , although when I call do_some_async_computation I would expect the pool to initiate a secondary thread for some_computation function ..which happens, after the computation is finished the my_callback_fct is executed accordingly, which emits a my_signal signal that is connected to the on_my_signal slot, which is executed as expected, but when altering the self.mylistwidget it gives a Runtime Error / QWidget runtime error redundant repaint detected 我在stackoverflow周围读到,为了从辅助执行线程更改gui,必须使用插槽信号机制,这是我在MyClass中所做的,尽管当我调用do_some_async_computation时,我希望池为some_computation函数启动辅助线程。 ..发生的情况是,在计算完成之后,将相应执行my_callback_fct ,并发出连接到on_my_signal插槽的my_signal信号,该信号已按预期执行,但是在更改self.mylistwidget时,会给出Runtime Error / QWidget runtime error redundant repaint detected

I haven't observed your actual error, but in a similar scenario we use a QueuedConnection to ensure the signal is passed correctly from one thread to the other. 我没有观察到您的实际错误,但是在类似的情况下,我们使用QueuedConnection来确保信号从一个线程正确传递到另一个线程。 This is done automagically for some people if the objects in question belong to different threads (QObject have a notion of the QThread that owns them). 如果有问题的对象属于不同的线程(QObject拥有它们的QThread的概念),那么对于某些人来说,这是自动完成的。 But in your case, all is done on one object, so Qt can't know. 但是在您的情况下,所有操作都在一个对象上完成,因此Qt无法知道。 Do

from PyQt5.QtCore import Qt
...
self.my_signal.connect(self.on_my_signal, Qt.QueuedConnection)

I solved this by using a QtCore.QThread instead of multiprocessing.Pool . 我通过使用QtCore.QThread而不是multiprocessing.Pool解决了这个问题。 I was thinking about the mechanism you talked about @deets and I said to myself that it should be in in the same context in order for Qt.QueuedConnection to work, so that's why I wanted to go with QThread . 我在考虑您谈论@deets的机制,我对自己说,为了使Qt.QueuedConnection起作用,它应该在同一上下文中,所以这就是为什么我想使用QThread的原因

class MyComputationalThread(PySide.QtCore.QThread):

    data_available = PySide.QtCore.Signal(str)
    def run(self):
        result = # ... do computations
        serialized_result = json.dumps(result) #  actually I use JSONEncoder here
        self.data_available.emit(serialized_result)

... and in my MyClass : ...在我的MyClass

class MyClass(QObject):
    # ...
    mythread = MyComputationalThread()
    # ...

    def __init__(self):
        # ...
        self.mythread.connect(do_something_with_serialized_data, PySide.QtCore.Qt.QueuedConnection)
        # ...

It works like a charm. 它像一种魅力。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM