PyQt:使用线程时访问对象

时间:2011-07-04 23:29:40

标签: python multithreading queue pyqt

我目前正在研究small markdown-editor,但我遇到了问题:

虽然速度非常快,但是降价模块不能发挥魔力,并且因为每次更改某些内容时它都会处理整个文本,所以程序将在例如时间内无响应。压制退格。

如何使用线程(子进程,QThread)来实现以下内容?

  1. 在处理过程中更改文本时,作业将被推送到队列中。如果队列已包含作业,则此作业将替换为新作业。
  2. 更改文本且队列中没有作业时,将执行新作业。
  3. 作业完成后,将执行队列中的作业。如果没有,我们就完成了。
  4. 澄清

    我不希望完全采用上述算法,而是一种实现持续但不慢的渲染类型的方法。我想在“背景”中激活渲染作业,但是一次一个,确保始终执行最新的渲染作业。

    1. 用户开始更改文字。
    2. 当前文本的渲染作业在另一个帖子中启动。
    3. 一旦完成并且渲染的HTML已经替换旧的HTML,就确定是否仍有渲染完成,即最新文本是刚渲染还是旧版本。
    4. 如果文字和渲染仍然不同步,请转到2。
    5. 请注意,澄清之上的算法是一种方法,其中3.(确定异步)被称为1线程队列。另请注意,只需要完成最新的工作,但我也希望完成随机的中间工作,以防止一次插入大量新输入的内容。

      最佳案例场景:在快速连续输入大型文档时,渲染视图每隔几个字左右更新一次,而编辑器始终响应。

2 个答案:

答案 0 :(得分:2)

对我来说,这似乎是QThreadPoolQRunnable的作业:

  • 创建一个派生自QRunnable的类,描述“渲染作业”
  • 创建一个QThreadPoolmaxThreadCount设置为1(非常重要,因为一次只能有一个渲染线程)。
  • 每次文本更改时,都会创建“渲染作业”类的实例(可能启用了autoDelete),并使用QThreadPool.start()将其添加到线程池中。 QThreadPool维护自己的挂起作业队列,因此如果当前正在运行另一个作业,则新作业不会丢失。在这种情况下,它会在当前作业完成后执行。

要限制创建的渲染作业数,您不应直接在.textChanged信号上启动作业,而应通过QTimer间接启动作业。每次,文本更改,重启计时器,如500毫秒超时,如果计时器实际发出.timeout,则只启动新的“渲染作业”。

实现“渲染作业”类时,请记住不要直接访问任何GUI类。相反,在“渲染作业”类中定义了一个信号,该信号在呈现完成后以渲染的HTML字符串作为参数发出,并将其与显示小部件的.setText()连接。

这并不是您要求的,因为正在运行的渲染作业永远不会中断,而是始终完成。因此,如果文本变化非常快(例如用户按住退格键),预览可能会在一定程度上失去同步。但是,我认为这是解决您问题的最简单,最直接的解决方案,因为它既不需要锁定也不需要同步,也不需要跟踪当前正在运行的作业。每个作业都以异乎寻常的方式运行,以“即发即忘”的方式运行。

答案 1 :(得分:0)

如何在每次文本更改时执行以下操作:检查呈现线程是否已经工作(标志),如果没有:让它呈现文本编辑器内容的副本。并且渲染线程在每次渲染结束时根据其最后一次输入检查编辑器的当前内容。如果存在差异:重新渲染。