เหตุใดเธรดหลักจึงถูกบล็อกหาก .connect ใช้ฟังก์ชันแลมบ์ดา

ฉันกำลังพยายามให้ปุ่มหมุนเธรดใหม่ที่ไม่ทำอะไรเลยนอกจากสลีปเป็นเวลา 30 วินาที อย่างไรก็ตาม เธรดหลักจะถูกบล็อกหากช่องเป็นฟังก์ชันแลมบ์ดา ไม่มีใครรู้ว่าเหตุใดจึงเป็นเช่นนี้และไม่ประพฤติตามที่ฉันคาดหวังไว้ นี่คือรหัสของฉัน:

    # ...
    def setup(self):
        # ...
        self.pushButton_TestConnection.clicked.connect(self.process)

    def process(self):
        self.worker_thread = QtCore.QThread()
        self.worker = Worker()
        self.worker.moveToThread(self.worker_thread)
        self.worker_thread.started.connect(lambda: self.worker.sleep(30))

        self.worker_thread.start()

class Worker(QtCore.QObject):
    def sleep(self, secs):
        time.sleep(secs)

มันทำงานได้ดีกับสิ่งต่อไปนี้

     self.worker_thread.started.connect(self.worker.sleep)

        self.worker_thread.start()

class Worker(QtCore.QObject):
    def sleep(self):
        time.sleep(30)

ขอบคุณ


person Kar    schedule 20.02.2015    source แหล่งที่มา
comment
ที่เกี่ยวข้อง: stackoverflow.com/q/23317195/1994235   -  person three_pineapples    schedule 21.02.2015


คำตอบ (1)


ใน Qt เธรดที่เรียกใช้โค้ดจะถูกกำหนดโดย ความสัมพันธ์ของเธรดของวัตถุที่รับสัญญาณ หากคุณเรียกเมธอดอ็อบเจ็กต์โดยตรงจากเธรดอื่น มันจะถูกดำเนินการในเธรดที่เรียก ไม่ว่าความสัมพันธ์ของเธรดของอ็อบเจ็กต์ที่ถูกเรียกจะเป็นอย่างไร

Lambdas และ python callables อื่น ๆ ไม่มีความสัมพันธ์ของเธรด (พวกมันไม่ใช่ QObjects มันเป็นเพียงคุณสมบัติที่ดีของ PyQt ที่ให้คุณเชื่อมต่อสัญญาณกับ python ที่สามารถเรียกได้) ดังนั้นพวกมันจะถูกดำเนินการใน main (GUI) เสมอ ) เธรด
ดังนั้นในกรณีนี้ แลมบ์ดาจะถูกดำเนินการในเธรด GUI ดังนั้นการเรียก worker.sleep จะถูกดำเนินการที่นั่นด้วย และจะบล็อกไว้จนกว่าการโทรจะกลับมา

เพื่อให้ทำงานได้ คุณต้องเชื่อมต่อสัญญาณ started เข้ากับช่องของวัตถุผู้ปฏิบัติงานโดยตรง หรือสื่อสารกับผู้ปฏิบัติงานโดยใช้สัญญาณที่คุณปล่อยออกมาจากแลมบ์ดา

person mata    schedule 20.02.2015