मैं अपने पायसाइड जीयूआई अनुप्रयोग में काफी आम बात करने की कोशिश कर रहा हूं: मैं कुछ सीपीयू-गहन कार्य को पृष्ठभूमि धागे में भेजना चाहता हूं ताकि मेरा जीयूआई रहता है उत्तरदायी और गणना के रूप में एक प्रगति संकेतक भी प्रदर्शित कर सकता है।पायसाइड/पीईक्यूटी - एक सीपीयू गहन धागा शुरू करना पूरे आवेदन को लटकता है
यहाँ मैं क्या कर रहा हूं (मैं PySide 1.1.1 का उपयोग कर रहा अजगर 2.7, लिनक्स x86_64 पर) है:
import sys
import time
from PySide.QtGui import QMainWindow, QPushButton, QApplication, QWidget
from PySide.QtCore import QThread, QObject, Signal, Slot
class Worker(QObject):
done_signal = Signal()
def __init__(self, parent = None):
QObject.__init__(self, parent)
@Slot()
def do_stuff(self):
print "[thread %x] computation started" % self.thread().currentThreadId()
for i in range(30):
# time.sleep(0.2)
x = 1000000
y = 100**x
print "[thread %x] computation ended" % self.thread().currentThreadId()
self.done_signal.emit()
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
self.work_thread = QThread()
self.worker = Worker()
self.worker.moveToThread(self.work_thread)
self.work_thread.started.connect(self.worker.do_stuff)
self.worker.done_signal.connect(self.work_done)
def initUI(self):
self.btn = QPushButton('Do stuff', self)
self.btn.resize(self.btn.sizeHint())
self.btn.move(50, 50)
self.btn.clicked.connect(self.execute_thread)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Test')
self.show()
def execute_thread(self):
self.btn.setEnabled(False)
self.btn.setText('Waiting...')
self.work_thread.start()
print "[main %x] started" % (self.thread().currentThreadId())
def work_done(self):
self.btn.setText('Do stuff')
self.btn.setEnabled(True)
self.work_thread.exit()
print "[main %x] ended" % (self.thread().currentThreadId())
def main():
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
आवेदन एक बटन के साथ एक एकल खिड़की प्रदर्शित करता है। जब बटन दबाया जाता है, तो मैं गणना करता हूं कि गणना के दौरान इसे स्वयं अक्षम कर दें। फिर, बटन पुनः सक्षम होना चाहिए।
क्या होता है, इसके बजाए, जब मैं बटन दबाता हूं तो गणना पूरी होने पर पूरी विंडो फ्रीज होती है और फिर, जब यह समाप्त हो जाती है, तो मैं एप्लिकेशन पर नियंत्रण प्राप्त करता हूं। बटन कभी अक्षम नहीं प्रतीत होता है। मैंने देखा एक मजेदार बात यह है कि अगर मैं एक सरल समय के साथ do_stuff()
में सीपीयू गहन गणना को प्रतिस्थापित करता हूं। नींद() कार्यक्रम अपेक्षित व्यवहार करता है।
मुझे नहीं पता कि क्या हो रहा है, लेकिन ऐसा लगता है कि दूसरी धागा की प्राथमिकता इतनी अधिक है कि यह वास्तव में निर्धारित होने से जीयूआई थ्रेड को रोक रहा है। यदि दूसरा धागा ब्लॉक किए गए राज्य में जाता है (जैसा कि यह sleep()
के साथ होता है), तो जीयूआई वास्तव में अपेक्षित रूप से इंटरफ़ेस को चलाने और अपडेट करने का मौका देता है। मैंने कार्यकर्ता थ्रेड प्राथमिकता को बदलने की कोशिश की, लेकिन ऐसा लगता है कि यह लिनक्स पर नहीं किया जा सकता है।
इसके अलावा, मैं थ्रेड आईडी मुद्रित करने का प्रयास करता हूं, लेकिन मुझे यकीन नहीं है कि मैं इसे सही तरीके से कर रहा हूं। यदि मैं हूं, तो थ्रेड एफ़िनिटी सही प्रतीत होती है।
मैंने पीईक्यूटी के साथ कार्यक्रम की भी कोशिश की और व्यवहार बिल्कुल वही है, इसलिए टैग और शीर्षक। अगर मैं इसे पायसाइड के बजाय पीईक्यूटी 4 के साथ चला सकता हूं तो मैं अपने पूरे एप्लिकेशन को पीईक्यूटी 4
मैं डाल 'time.sleep (0)' 'time.sleep के बजाय (0.2)' उदाहरण में टिप्पणी और, दुर्भाग्य से, समस्या हल नहीं होती कोशिश की। मैंने देखा कि 'time.sleep (0.05)' जैसे मानों के साथ बटन अपेक्षित व्यवहार करता है। एक कामकाज के रूप में, मैं कार्यकर्ता को प्रति सेकंड केवल कुछ बार प्रगति की रिपोर्ट करने के लिए स्थापित कर सकता हूं और जीयूआई अपडेट को स्वयं छोड़ने के लिए सो सकता हूं। – user1491306
धागे और जीयूआई के लिए कामकाज हैं (जैसे कि http://code.activestate.com/recipes/578154)। –
मैं इस तरह से समाप्त हो गया: मैंने 'नींद' लगाई जहां गणना शुरू होती है, और जब भी प्रगति संकेतक अद्यतन होता है तो मैं "abort" बटन काम करने के लिए 'app.processEvents()' को कॉल करता हूं। – user1491306