Python, PyQt5 GUI начинает тормозить при запуске большого количества QThreads

Я пишу приложение на Python 3.9 с пользовательским интерфейсом, используя PyQt5. В моем приложении я использую большое количество потоков QThread ( основная функция каждого потока - отправка HTTP запросов, обработка ответов, и передача результатов выполнения (посредством механизма сигнал-слот'ов) обратно в поток GUI, для отображения данных внутри QTableWIdget) Используется обычно от 300 и до 5000 потоков единовременно

Суть проблемы следующая - когда запускается такое количество потоков, и начинается их выполнение, интерфейс начинает сильно тормозить, до момента пока не закончится выполнение всех потоков. Отключение сигналов, которые связаны со слотами , изменяющими виджеты в GUI - ничего не меняет, GUI все также продолжает тормозить.

Для теста, я пробовал запускать такое же количество потоков, которые во время своего выполнения, только испускают аналогичные сигналы в цикле с небольшой задержкой, без выполнения другой логики - в таком случае все становится нормально, GUI без задержек обновляется и отвечает на все пользовательские команды. Из чего я могу сделать вывод, что проблема не в большом количестве испускаемых\принимаемых сигналов.

Вопрос , что провоцирует торможение GUI, в моем случае, и есть ли какие-то возможные решения чтобы сделать мой интерфейс более отзывчивым в данной ситуации? Читал про GIL, но не уверен, что это связано с ним.

Пример кода в котором присутствует проблема, почищенный от лишних функций:

main.py

import sys
import os
import time
import requests
from datetime import datetime

from PyQt5 import QtWidgets, QtCore, QtGui, uic
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *


MainWidget, _ = uic.loadUiType(os.path.join(os.path.dirname(__file__),'ui.ui'))

class MainWindow(QtWidgets.QMainWindow, MainWidget):
    def __init__(self):
        super(MainWindow,self).__init__()
        self.setupUi(self)

        self.threads = {}
        self.loaddata()
        self.startButton.clicked.connect(self.start_work)

    def loaddata(self):
        """ Заполнение таблицы (виджет уже создан ранее в Qt Designer) """
        self.table.setRowCount(500)
        self.table.setColumnCount(5)
        for i in range(500):
            self.table.setItem(i, 0, QtWidgets.QTableWidgetItem(str(i)))
            self.table.setItem(i, 1, QtWidgets.QTableWidgetItem(str(i)))
            self.table.setItem(i, 2, QtWidgets.QTableWidgetItem(str(i)))
            self.table.setItem(i, 3, QtWidgets.QTableWidgetItem(str(i)))
            self.table.setItem(i, 4, QtWidgets.QTableWidgetItem(str(i)))

    def start_work(self):
        """ Запускаем потоки
            Кол-во потоков равно кол-ву строк в таблице
            В данном примере запустится 500 потоков """
        for row in range(self.table.rowCount()):
            item = self.table.item(row,0)
            worker = Worker(item)
            thread = QThread()
            worker.moveToThread(thread)
            thread.started.connect(worker.run)
            worker.mysignal.connect(self.on_signal)
            worker.finished.connect(self.on_finish_thread)
            self.threads[str(item)] = [thread, worker]

            thread.start()
            worker.deleteLater()

    def on_finish_thread(self, item):
        """ Останавливаем поток и удаляем QThread и QObject из словаря """
        thread = self.threads[str(item)][0]
        worker = self.threads[str(item)][1]
        thread.quit()
        thread.wait()
        try:
            del self.threads[str(item)]
        except Exception as e:
            print(e)

    def on_signal(self, item, msg):
        """ Устанавливается значение в соответствующую ячейку таблицы """
        self.table.item(item.row(), 2).setText(msg)


class Worker(QObject):
    mysignal = pyqtSignal(object, str)
    finished = pyqtSignal(object)

    def __init__(self, item):
        self.item = item
        super().__init__()

    def run(self):
        """ Отправляем запросы в цикле и испускаем сигналы с результатом """
        for i in range(100):
            try:
                requests.get('https://vk.com/')
                self.mysignal.emit(self.item, f'Response:ok {datetime.now()}')
            except Exception as e:
                self.mysignal.emit(self.item, f'Response:error {e}')
            time.sleep(0.1)
        self.finished.emit(self.item)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

ui.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>570</width>
    <height>684</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <widget class="QTableWidget" name="table">
   <property name="geometry">
    <rect>
     <x>48</x>
     <y>126</y>
     <width>457</width>
     <height>359</height>
    </rect>
   </property>
   <property name="selectionBehavior">
    <enum>QAbstractItemView::SelectRows</enum>
   </property>
   <attribute name="horizontalHeaderVisible">
    <bool>true</bool>
   </attribute>
   <attribute name="verticalHeaderVisible">
    <bool>true</bool>
   </attribute>
   <column>
    <property name="text">
     <string>1</string>
    </property>
   </column>
   <column>
    <property name="text">
     <string>2</string>
    </property>
   </column>
   <column>
    <property name="text">
     <string>3</string>
    </property>
   </column>
  </widget>
  <widget class="QPushButton" name="startButton">
   <property name="geometry">
    <rect>
     <x>227</x>
     <y>523</y>
     <width>75</width>
     <height>23</height>
    </rect>
   </property>
   <property name="text">
    <string>start</string>
   </property>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>


Ответы (0 шт):