Hi all,

I'm heaving problems with offloading some CPU-intensive calculations to a separate thread. My GUI's response is too slow, sometimes it takes several seconds to repaint/refresh. I have a dual-core CPU with recent amd64-Linux running.

Maybe there is some misunderstanding: so far I thought it's only about starting the background thread and let it go. I have been reading Keeping the GUI responsive but it has not really help me yet. As you can see in the code (below), my thread does not do anything useful except from eating loads of CPU-cycles.

Here is what I've tried so far:


The only thing that helped me a little bit was setting the thread priority. Is there anything I can do to let my program have a better response time? I'm especially interested in solutions that work with third-party code, meaning invoking CPU-intensive methods from external libraries which I cannot extend with Qt-related functionality.

Thank you for your support in advance,
Rainer

Qt Code:
  1. import sys
  2. from PySide import QtGui, QtCore, QtUiTools
  3.  
  4. # Import the compiled UI module
  5. from customwidget import Ui_customWidget
  6.  
  7.  
  8. class CCalculation(QtCore.QThread):
  9.  
  10. sProgress = QtCore.Signal(int)
  11. sFinished = QtCore.Signal()
  12.  
  13. def __init__(self, pData):
  14. super(CCalculation, self).__init__()
  15. self.mData = pData
  16.  
  17. def run(self):
  18. lCnt = 0
  19. lTotal = len(self.mData)
  20. # lLast = datetime.datetime.now()
  21. for lNum in self.mData:
  22. self.mData[lCnt] = lNum ** 2
  23. # lNow = datetime.datetime.now()
  24. # if (lNow - lLast) > datetime.timedelta(0, 0, 100000):
  25. # lLast = lNow
  26. # QtCore.QCoreApplication.processEvents()
  27. if 100 * lCnt / lTotal % 10 == 0:
  28. self.sProgress.emit(100 * lCnt / lTotal)
  29. lCnt = 0
  30. self.sFinished.emit()
  31.  
  32. class CMain:
  33.  
  34. sNumElements = 200000
  35. sAccessElement = 22
  36.  
  37. def __init__(self):
  38. # GUI code
  39. self.mApp = QtGui.QApplication(sys.argv)
  40. self.mWindow = QtGui.QMainWindow()
  41. self.mWidget = QtGui.QWidget()
  42. self.mFactory = Ui_customWidget()
  43. self.mFactory.setupUi(self.mWidget)
  44. self.mWindow.setCentralWidget(self.mWidget)
  45.  
  46. # Threading
  47. self.mData = range(CMain.sNumElements)
  48. self.mThread = CCalculation(self.mData)
  49. self.mThreadRunning = QtCore.QMutex()
  50.  
  51. # wire signals and slots
  52. self.mThread.sProgress.connect(self.mFactory.progressBar.setValue)
  53. self.mThread.sFinished.connect(self.threadFinished)
  54. self.mFactory.processButton.clicked.connect(self.startThread)
  55.  
  56. def startThread(self):
  57. if self.mThreadRunning.tryLock() == True:
  58. #self.mThread.start(QtCore.QThread.IdlePriority)
  59. self.mThread.start()
  60.  
  61. def threadFinished(self):
  62. self.mFactory.textEdit.setText(str(self.mData[CMain.sAccessElement]))
  63. self.mThreadRunning.unlock()
  64.  
  65. def run(self):
  66. self.mWindow.show()
  67. lReturn = self.mApp.exec_()
  68. self.mThread.quit()
  69. self.mThread.wait()
  70. sys.exit(lReturn)
  71.  
  72.  
  73. if __name__ == "__main__":
  74. lMain = CMain()
  75. lMain.run()
To copy to clipboard, switch view to plain text mode