程序必须等待两个线程(Sql查询执行)完成

2024-06-16 11:26:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个程序比较数据库表的值,我已经在PyQt5中创建了一个GUI。我已经创建了两个线程,一个用于查询每个表,然后程序必须等待两个线程完成。我的代码在下面

from PySide2 import QtWidgets
from PySide2 import QtGui
from PySide2 import QtCore
from Main_interface import Ui_mainWindow
import pandas as pd


class mainWindow(QtWidgets.QMainWindow, Ui_mainWindow):

  sqlClicked1 = QtCore.Signal(str)
  sqlClicked2 = QtCore.Signal(str)

  def __init__(self, parent=None):
    super(mainWindow, self).__init__(parent)
    self.setupUi(self)

    self.thread = QtCore.QThread(self)
    self.thread.start()
    self.obj = Worker()
    self.obj.moveToThread(self.thread)
    self.sqlClicked.connect(self.obj.runsql_MC)
    self.sqlClicked1.connect(self.obj.runsql_IRI)
    self.obj.error.connect(self.on_error)


 def run_report(self):
    sqlquery1 = "Select * from table1"
    sqlquery2 = "Select * from table2"

    df1 = self.sqlClicked1.emit(sqlquery1)
    df2 = self.sqlClicked2.emit(sqlquery2)

    self.sqlClicked1.finished.connect(self.on_finished)
    self.sqlClicked2.finished.connect(self.on_finished)

    print("SQL execution is done")

    #Then i am calling function to compare two dataframes


class Worker(QtCore.QObject):
   finished = QtCore.Signal()
   result = QtCore.Signal(object)

   @QtCore.Slot(str)
   def runsql_MC(self, sqlquery_MC):
     print("Thread1 is working")
     try:
        df1 = pd.read_sql(sql=sqlquery_MC, con=cnxn)
     except:
        traceback.print_exc()
     else:
        self.signals.result.emit(df1)  # Return the result of the processing
     finally:
        self.signals.finished.emit()  # Done

  @QtCore.Slot(str)
  def runsql_IRI(self, sqlquery_IRI):
    print("Thread2 is working")
    try:
        df2 = pd.read_sql(sql=sqlquery_IRI, con=cnxn)
    except:
        traceback.print_exc()
    else:
        self.signals.result.emit(df2)  
    finally:
        self.signals.finished.emit()  


if __name__ == '__main__':
  import sys
  app = QtWidgets.QApplication(sys.argv)
  my_app = mainWindow()
  my_app.show()
  sys.exit(app.exec_())

self.sqlClicked1.emit(sqlquery1)self.sqlClicked2.emit(sqlquery2)正在调用相应的线程runsql_MC()runsql_IRI。然后我需要等到两个线程完成后才能开始比较过程。目前还没有发生。你知道吗


Tags: fromimportselfobjconnectmc线程print
2条回答

我不太确定它是否是用你的代码写的,但是你有没有用join()语句来等待线程结束?当从mainWindow类中唤醒def __init__()方法中的这两个线程时,应该使用它

尽管你的代码不是MRE,但要表现出你对各种概念的无知。你知道吗

  • 信号的发射并不意味着作为结果获得数据,因为它将异步发送。

  • 在代码中,即使调用2个查询,也不意味着每个查询都在不同的线程上运行,因为工作线程位于单个线程中。

  • 您的runsql\u MC和runsql\u IRI方法是多余的,因为它们是同一事物的模板。

  • 除其他错误外,例如没有名为sqlClicked的对象/信号,您没有声明对象信号等。

这样做的目的是让每个查询都有一个位于不同线程中的worker,并创建一个类来处理等待数据的worker,并在它们完成工作时消除它们。你知道吗

from functools import partial
import sqlite3
import pandas as pd
from PySide2 import QtCore, QtGui, QtWidgets


class Worker(QtCore.QObject):
    finished = QtCore.Signal()
    result = QtCore.Signal(object)

    @QtCore.Slot(str)
    def runsql(self, query):
        cnxn = sqlite3.connect("test.db")
        print("Thread1 is working")
        try:
            df1 = pd.read_sql(sql=query, con=cnxn)
        except:
            traceback.print_exc()
        else:
            self.result.emit(df1)  # Return the result of the processing
        finally:
            self.finished.emit()  # Done


class SqlManager(QtCore.QObject):
    results = QtCore.Signal(list)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.workers_and_threads = {}
        self.dataframes = []

    def execute_queries(self, queries):
        for query in queries:
            thread = QtCore.QThread(self)
            thread.start()
            worker = Worker()
            worker.result.connect(self.onResults)
            worker.moveToThread(thread)
            self.workers_and_threads[worker] = thread
            # launch task
            wrapper = partial(worker.runsql, query)
            QtCore.QTimer.singleShot(0, wrapper)

    @QtCore.Slot(object)
    def onResults(self, result):
        worker = self.sender()
        thread = self.workers_and_threads[worker]
        thread.quit()
        thread.wait()
        del self.workers_and_threads[worker]
        worker.deleteLater()
        self.dataframes.append(result)
        if not self.workers_and_threads:
            self.results.emit(self.dataframes)
            self.dataframes = []


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.push_button = QtWidgets.QPushButton("Run Report")
        self.push_button.clicked.connect(self.run_report)
        self.setCentralWidget(self.push_button)

        self.manager = SqlManager(self)
        self.manager.results.connect(self.onResults)

    @QtCore.Slot()
    def run_report(self):
        sqlquery1 = "Select * from table1"
        sqlquery2 = "Select * from table2"
        queries = [sqlquery1, sqlquery2]
        self.manager.execute_queries(queries)
        self.push_button.setEnabled(False)

    @QtCore.Slot(list)
    def onResults(self, dataframes):
        print(dataframes)
        self.push_button.setEnabled(True)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    my_app = MainWindow()
    my_app.show()
    sys.exit(app.exec_())

相关问题 更多 >