- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个创建 QRunnables 并在 QThreadPool 实例中启动它们的类。
我的线程运行良好,但如果用户想退出应用程序,应用程序需要很长时间才能停止。当然是因为发起的请求需要时间。
这是我如何使用 QThreadPool、QRunnables 的片段代码:
import sys
from PyQt5.Qt import QThreadPool, QApplication, QWidget, QVBoxLayout
from PyQt5.Qt import QTimer, QObject, QPushButton, QLabel
from PyQt5.Qt import QRunnable
class BackendQRunnable(QRunnable):
"""
Class who create a QThread to trigger requests
"""
def __init__(self, task):
super(BackendQRunnable, self).__init__()
self.task = task
def run(self):
"""
Run the QRunnable. Trigger actions depending on the selected task
"""
# Here I make long requests
if 'user' in self.task:
self.query_user_data()
elif 'host' in self.task:
self.query_hosts_data()
elif 'service' in self.task:
self.query_services_data()
elif 'alignakdaemon' in self.task:
self.query_daemons_data()
elif 'livesynthesis' in self.task:
self.query_livesynthesis_data()
elif 'history' in self.task:
self.query_history_data()
elif 'notifications' in self.task:
self.query_notifications_data()
else:
pass
@staticmethod
def query_user_data():
"""
Launch request for "user" endpoint
"""
print('Query user data')
@staticmethod
def query_hosts_data():
"""
Launch request for "host" endpoint
"""
print('Query hosts')
@staticmethod
def query_services_data():
"""
Launch request for "service" endpoint
"""
print("Query services")
@staticmethod
def query_daemons_data():
"""
Launch request for "alignakdaemon" endpoint
"""
print('Query daemons')
@staticmethod
def query_livesynthesis_data():
"""
Launch request for "livesynthesis" endpoint
"""
print('query livesynthesis')
@staticmethod
def query_history_data():
"""
Launch request for "history" endpoint but only for hosts in "data_manager"
"""
print('Query history')
@staticmethod
def query_notifications_data():
"""
Launch request for "history" endpoint but only for notifications of current user
"""
print('Query notifications')
class ThreadManager(QObject):
"""
Class who create BackendQRunnable to periodically request on a Backend
"""
def __init__(self, parent=None):
super(ThreadManager, self).__init__(parent)
self.backend_thread = BackendQRunnable(self)
self.pool = QThreadPool.globalInstance()
self.tasks = self.get_tasks()
def start(self):
"""
Start ThreadManager
"""
print("Start backend Manager...")
# Make a first request
self.create_tasks()
# Then request periodically
timer = QTimer(self)
timer.setInterval(10000)
timer.start()
timer.timeout.connect(self.create_tasks)
@staticmethod
def get_tasks():
"""
Return the tasks to run in BackendQRunnable
:return: tasks to run
:rtype: list
"""
return [
'notifications', 'livesynthesis', 'alignakdaemon', 'history', 'service', 'host', 'user',
]
def create_tasks(self):
"""
Create tasks to run
"""
for cur_task in self.tasks:
backend_thread = BackendQRunnable(cur_task)
# Add task to QThreadPool
self.pool.start(backend_thread)
def exit_pool(self):
"""
Exit all BackendQRunnables and delete QThreadPool
"""
# When trying to quit, the application takes a long time to stop
self.pool.globalInstance().waitForDone()
self.pool.deleteLater()
sys.exit(0)
if __name__ == '__main__':
app = QApplication(sys.argv)
thread_manager = ThreadManager()
thread_manager.start()
layout = QVBoxLayout()
label = QLabel("Start")
button = QPushButton("DANGER!")
button.pressed.connect(thread_manager.exit_pool)
layout.addWidget(label)
layout.addWidget(button)
w = QWidget()
w.setLayout(layout)
w.show()
sys.exit(app.exec_())
exit_pool
,我等到线程完成并删除 QThreadPool 实例...
QRunnable
与
QThread
.我删除了
QThreadPool
我自己在列表中管理线程。我还添加了一个
pyqtSignal
为了停止 QTimer 并通过
quit()
关闭正在运行的线程功能。
import sys
from PyQt5.Qt import QThread, QApplication, QWidget, QVBoxLayout
from PyQt5.Qt import QTimer, QObject, QPushButton, QLabel, pyqtSignal
class BackendQThread(QThread):
"""
Class who create a QThread to trigger requests
"""
quit_thread = pyqtSignal(name='close_thread')
def __init__(self, task):
super(BackendQThread, self).__init__()
self.task = task
def run(self):
"""
Run the actions depending on the selected task
"""
# Here I make long requests
if 'user' in self.task:
self.query_user_data()
elif 'host' in self.task:
self.query_hosts_data()
elif 'service' in self.task:
self.query_services_data()
elif 'alignakdaemon' in self.task:
self.query_daemons_data()
elif 'livesynthesis' in self.task:
self.query_livesynthesis_data()
elif 'history' in self.task:
self.query_history_data()
elif 'notifications' in self.task:
self.query_notifications_data()
else:
pass
@staticmethod
def query_user_data():
"""
Launch request for "user" endpoint
"""
print('Query user data')
@staticmethod
def query_hosts_data():
"""
Launch request for "host" endpoint
"""
print('Query hosts')
@staticmethod
def query_services_data():
"""
Launch request for "service" endpoint
"""
print("Query services")
@staticmethod
def query_daemons_data():
"""
Launch request for "alignakdaemon" endpoint
"""
print('Query daemons')
@staticmethod
def query_livesynthesis_data():
"""
Launch request for "livesynthesis" endpoint
"""
print('query livesynthesis')
@staticmethod
def query_history_data():
"""
Launch request for "history" endpoint but only for hosts in "data_manager"
"""
print('Query history')
@staticmethod
def query_notifications_data():
"""
Launch request for "history" endpoint but only for notifications of current user
"""
print('Query notifications')
class ThreadManager(QObject):
"""
Class who create BackendQThread to periodically request on a Backend
"""
def __init__(self, parent=None):
super(ThreadManager, self).__init__(parent)
self.tasks = self.get_tasks()
self.timer = QTimer()
self.threads = []
def start(self):
"""
Start ThreadManager
"""
print("Start backend Manager...")
# Make a first request
self.create_tasks()
# Then request periodically
self.timer.setInterval(10000)
self.timer.start()
self.timer.timeout.connect(self.create_tasks)
@staticmethod
def get_tasks():
"""
Return the available tasks to run
:return: tasks to run
:rtype: list
"""
return [
'notifications', 'livesynthesis', 'alignakdaemon', 'history', 'service', 'host', 'user',
]
def create_tasks(self):
"""
Create tasks to run
"""
# Here I reset the list of threads
self.threads = []
for cur_task in self.tasks:
backend_thread = BackendQThread(cur_task)
# Add task to QThreadPool
backend_thread.start()
self.threads.append(backend_thread)
def stop(self):
"""
Stop the manager and close all QThreads
"""
print("Stop tasks")
self.timer.stop()
for task in self.threads:
task.quit_thread.emit()
print("Tasks finished")
if __name__ == '__main__':
app = QApplication(sys.argv)
layout = QVBoxLayout()
widget = QWidget()
widget.setLayout(layout)
thread_manager = ThreadManager()
start_btn = QPushButton("Start")
start_btn.clicked.connect(thread_manager.start)
layout.addWidget(start_btn)
stop_btn = QPushButton("Stop")
stop_btn.clicked.connect(thread_manager.stop)
layout.addWidget(stop_btn)
widget.show()
sys.exit(app.exec_())
最佳答案
您无法停止 QRunnable
一旦开始。但是,您可以执行一些简单的操作来减少示例中的等待时间。
首先,您可以停止计时器,使其不再添加任何任务。其次,您可以clear the thread-pool以便它删除任何挂起的任务。第三,你可以试试setting a smaller maximum thread count看看它是否仍然达到可接受的性能。默认情况下,线程池将使用 QThread.idealThreadCount()
设置最大线程数 - 这通常意味着系统上的每个处理器核心一个。
最后一个选择是提供一种方法来中断在您的可运行程序中执行的代码。只有当代码运行一个循环,该循环可以定期检查一个标志以查看它是否应该继续时,这才真正成为可能。在您的示例中,您似乎可以为标志使用单个共享类属性,因为所有任务都调用静态方法。但是,如果代码不能以这种方式中断,则您无能为力 - 您只需等待当前正在运行的任务完成即可。
关于qt - PyQt:带有 QRunnables 的 QThreadPool 需要时间退出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46511239/
我正在尝试用 C 语言编写一个使用 gstreamer 的 GTK+ 应用程序。 GTK+ 需要 gtk_main() 来执行。 gstreamer 需要 g_main_loop_run() 来执行。
我已经使用 apt-get 安装了 opencv。我得到了以下版本的opencv2,它工作正常: rover@rover_pi:/usr/lib/arm-linux-gnueabihf $ pytho
我有一个看起来像这样的 View 层次结构(基于其他答案和 Apple 的使用 UIScrollView 的高级 AutoLayout 指南): ScrollView 所需的2 个步骤是: 为 Scr
我尝试安装 udev。 udev 在 ./configure 期间给我一个错误 --exists: command not found configure: error: pkg-config and
我正在使用 SQLite 3。我有一个表,forums,有 150 行,还有一个表,posts,有大约 440 万行。每个帖子都属于一个论坛。 我想从每个论坛中选择最新帖子的时间戳。如果我使用 SEL
使用 go 和以下包: github.com/julienschmidt/httprouter github.com/shwoodard/jsonapi gopkg.in/mgo.v2/bson
The database仅包含 2 个表: 钱包(100 万行) 事务(1500 万行) CockroachDB 19.2.6 在 3 台 Ubuntu 机器上运行 每个 2vCPU 每个 8GB R
我很难理解为什么在下面的代码中直接调用 std::swap() 会导致编译错误,而使用 std::iter_swap 编译却没有任何错误. 来自 iter_swap() versus swap() -
我有一个非常简单的 SELECT *用 WHERE NOT EXISTS 查询条款。 SELECT * FROM "BMAN_TP3"."TT_SPLDR_55E63A28_59358" SELECT
我试图按部分组织我的 .css 文件,我需要从任何文件访问文件组中的任何类。在 Less 中,我可以毫无问题地创建一个包含所有文件导入的主文件,并且每个文件都导入主文件,但在 Sass 中,我收到一个
Microsoft.AspNet.SignalR.Redis 和 StackExchange.Redis.Extensions.Core 在同一个项目中使用。前者需要StackExchange.Red
这个问题在这里已经有了答案: Updating from Rails 4.0 to 4.1 gives sass-rails railties version conflicts (4 个答案) 关
我们有一些使用 Azure DevOps 发布管道部署到的现场服务器。我们已经使用这些发布管道几个月了,没有出现任何问题。今天,我们在下载该项目的工件时开始出现身份验证错误。 部署组中的节点显示在线,
Tip: instead of creating indexes here, run queries in your code – if you're missing any indexes, you
你能解释一下 Elm 下一个声明中的意思吗? (=>) = (,) 我在 Elm architecture tutorial 的例子中找到了它 最佳答案 这是中缀符号。实际上,这定义了一个函数 (=>
我需要一个 .NET 程序集查看器,它可以显示低级详细信息,例如元数据表内容等。 最佳答案 ildasm 是 IL 反汇编程序,具有低级托管元数据 token 信息。安装 Visual Studio
我有两个列表要在 Excel 中进行比较。这是一个很长的列表,我需要一个 excel 函数或 vba 代码来执行此操作。我已经没有想法了,因此转向你: **Old List** A
Closed. This question does not meet Stack Overflow guidelines。它当前不接受答案。 想要改善这个问题吗?更新问题,以便将其作为on-topi
我正在学习 xml 和 xml 处理。我无法很好地理解命名空间的存在。 我了解到命名空间帮助我们在 xml 中分离相同命名的元素。我们不能通过具有相同名称的属性来区分元素吗?为什么命名空间很重要或需要
我搜索了 Azure 文档、各种社区论坛和 google,但没有找到关于需要在公司防火墙上打开哪些端口以允许 Azure 所有组件(blob、sql、compute、bus、publish)的简洁声明
我是一名优秀的程序员,十分优秀!