第六国际 2024-09-20 21:05 采纳率: 53.8%
浏览 13
已结题

Pyqt 如何正确的关掉Qthread,并且释放其中的锁?

我项目使用锁,当把正在分析的任务(每个任务对应一个Qthread)通过teminate中止后,如果锁没有释放,待执行的任务开始执行后会被卡住,无法执行下去,Qthread中的analyse方法执行时间要10分钟以上,如何正确的中止Qthread, 使它立即结束运行,并释放他内部的锁啊?

img

上个任务中止后,锁没有释放,当前任务一直被卡住,十几分钟了,一动不动,也不报错

img

# 执行操作的线程
class WorkerThread(QThread):
    _signal = pyqtSignal(object)

    def __init__(self, param=None):
        super().__init__()
        self.param = param

    def run(self):
        try:
            logger.info('running')
            analyse(self.param)
            self._signal.emit(self.param)
        except Exception as e:
            traceback.print_exc()
            analyse_q.put(logMsg("操作异常"))
            logger.error(traceback.format_exc())
class PythonToJS(QObject):
    mySqlite = SqliteTool()

    def __init__(self, view):
        super().__init__()
        self.view = view
        self.th = None
   # 启动任务
    def run(self, reportId):
        try:
            print('run')
            self.th = WorkerThread(reportId)
            self.th._signal.connect(self.finished)
            self.th.start()
        except Exception as e:
            print('e', e)
            logger.error(traceback.format_exc())

  # 终止任务
    @pyqtSlot(str)
    def terminate(self, s):
        print('terminate', s)
        logger.info('terminate')
        try:
            product = json.loads(s)['parameter']
            if product:
                remove_task(task_q, product['reportId'])
                if product['analyseStatus'] == 1:
                    if self.th:
                        self.th.terminate()
                        self.th = None
                        remove_task(running_q, product['reportId'])
                        analyse_q.put(logMsg(""))
                        analyse_q.put(logMsg("*******************************"))
                        analyse_q.put(logMsg("用户终止分析..."))
                        analyse_q.put(logMsg("*******************************"))
                        analyse_q.put(logMsg(""))
                # 更新状态
                self.mySqlite.update(
                    "update fof_amt_product_report set analyse_status = 4 where report_id = ?", (product['reportId'],))
            obj = json.dumps({'ANS_MSG_HDR': {'MSG_CODE': "200", "MSG_TEXT": "success"}},
                             ensure_ascii=False)
            self.view.page().runJavaScript('%s(%s)' % ('onTerminate', obj))
        except Exception as e:
            print(e)
            logger.error(traceback.format_exc())

class SqliteTool(object):
    """
       简单sqlite数据库工具类
       编写这个类主要是为了封装sqlite,继承此类复用方法
       """
    def __init__(self, dbName="data.db", timeout = 10):
        """
        初始化连接——使用完需关闭连接
        :param dbName: 连接库的名字,注意,以'.db'结尾
        """
        self.dbName = dbName
        self.lockTimeout = timeout
        self._lock = threading.Lock()

    @contextmanager
    def _locked_cursor(self):
        try:
            # 连接数据库
            self._conn = sqlite3.connect(self.dbName, timeout=self.lockTimeout)
            # 开启 WAL 模式, 提升并发性能
            self._conn.execute('PRAGMA journal_mode = WAL;')
            self._conn.execute("PRAGMA synchronous=NORMAL;")
            self._conn.row_factory = dict_factory
            # 创建游标
            self._cur = self._conn.cursor()
            yield self._cur
            self._conn.commit()
        except Exception as e:
            self._conn.rollback()
            raise e
        finally:
            self._cur.close()
            self._conn.close()

    # 插入或更新表数据,一次插入或更新一条数据
    def insert(self, sql: str, value: tuple):
        """
        插入或更新单条表记录
        :param sql: insert语句或update语句
        :param value: 插入或更新的值,形如()
        :return: True表示插入或更新成功
        """
        try:
            with self._lock:
                with self._locked_cursor() as cur:
                    cur.execute(sql, value)
                    return True
        except Exception as e:
            print("insert error", e)
            return False

        # 插入或更新表数据,一次插入或更新一条数据

    def update(self, sql: str, value: tuple):
        """
        插入或更新单条表记录
        :param sql: insert语句或update语句
        :param value: 插入或更新的值,形如()
        :return: True表示插入或更新成功
        """

        with self._lock:
            with self._locked_cursor() as cur:
                try:
                    cur.execute(sql, value)
                    print('update success')
                except Exception as e:
                    print('update error', e)
  • 写回答

24条回答 默认 最新

  • 阿里嘎多学长 2024-09-20 21:06
    关注
    获得7.50元问题酬金

    AIGC生成:


    Pyqt 中正确地关闭 Qthread 并释放锁

    你遇到的问题是 Qthread 中止后,锁没有释放,导致后续任务无法执行。这个问题是因为 Qthread 中止后,线程仍然持有锁,导致其他线程无法访问该锁。

    以下是一些可能的解决方法:

    1. 使用 QThread::terminate() 方法时,确保锁已经释放 在 QThread::terminate() 方法中,锁已经释放,可以使用 QMutex::lock() 方法来确保锁已经释放。
    mutex.lock();
    // 释放锁
    mutex.unlock();
    
    1. 使用 QThread::quit() 方法 QThread::quit() 方法可以安全地关闭 Qthread,而不需要中止线程。锁将被释放,后续任务可以继续执行。
    thread.quit();
    
    1. 使用 QThread::requestInterruption() 方法 QThread::requestInterruption() 方法可以请求 Qthread 中止,但不会强制中止。锁将被释放,后续任务可以继续执行。
    thread.requestInterruption();
    
    1. 使用 QThread::wait() 方法 QThread::wait() 方法可以等待 Qthread 完成当前任务,然后释放锁。锁将被释放,后续任务可以继续执行。
    thread.wait();
    
    1. 使用 QThread::exit() 方法 QThread::exit() 方法可以安全地关闭 Qthread,而不需要中止线程。锁将被释放,后续任务可以继续执行。
    thread.exit();
    
    1. 使用 QMutex::tryLock() 方法 QMutex::tryLock() 方法可以尝试获取锁,如果锁已经被持有,则返回 false。可以使用这个方法来确保锁已经释放。
    if (!mutex.tryLock()) {
        // 锁已经被持有
    }
    

    这些方法可以帮助你正确地关闭 Qthread 并释放锁,从而解决你遇到的问题。

    评论

报告相同问题?

问题事件

  • 系统已结题 9月28日
  • 修改了问题 9月20日
  • 修改了问题 9月20日
  • 修改了问题 9月20日
  • 展开全部

悬赏问题

  • ¥30 comsol仿真等离激元
  • ¥15 静电纺丝煅烧后如何得到柔性纤维
  • ¥15 (标签-react native|关键词-镜像源)
  • ¥100 照片生成3D人脸视频
  • ¥15 伪装视频时长问题修改MP4的时长问题,
  • ¥15 JETSON NANO
  • ¥15 VS开发qt时如何在paintgl函数中用pushbutton控制切换纹理
  • ¥20 关于 openpyxl 处理excel文件地问题
  • ¥15 MS中不知道高分子的构型怎么构建模型
  • ¥60 QQOP数据,什么是op数据号,怎么提取op数据!能不能大量提取(语言-c语言)