在Qt应用程序代码中Class A有一个成员方法method1().我想在另一个成员函数中调用此方法并在另一个线程中method2()运行mehtod1().但是我从qt文档中发现的是以下内容.
class MyThread(假设)来自QThread.run()使用所需的代码覆盖函数方法.MyThreadin 的对象,Class A然后在任何地方调用run函数.但上面看起来有点复杂.在Qt中是否有任何机制,以便我可以立即创建一个新的QThread(没有继承)method1()并method2()使用此线程运行,然后method1()在执行完成后返回?
如果我不清楚我的问题,请告诉我.
编辑:在此修订/更新之前这个问题的主要部分是如何终止 QThread。这个问题已经解决了,问题正在修改为如何终止正在进行的请求剩余对象。
http://docs.python-requests.org/en/v0.10.4/user/advanced/#asynchronous-requests 看来使用异步请求仍然会阻塞 - 用户无法在发布过程中取消发布。
基本上这是所需的功能:当用户按下 时Stop Uploading,上传必须立即停止,我可以使用 stop() 停止线程,但是只有在循环再次循环后才会检查是否应该停止。
所以基本上,应该可以使用异步请求,让我检查是否应该在请求期间取消它,但是,我不知道如何取消。
有什么建议么?帖子的前一部分仍然相关,因此如下。
请注意,如何终止 QThread 的最初问题已经解决,因此下面的代码并不是太重要,它只是用于上下文,我现在需要帮助的是我刚才描述的内容。
我一直在编写一个程序,它是一个照片上传器,我创建了一个上传文件的线程。我不知道如何退出线程。我尝试过从这里读到的建议:
1)我尝试了一个 bool 标志,将它包裹在方法和执行工作的 for 语句周围。
2)我使用了“with”,然后尝试设置例外。
我希望能够取消上传,最好是尽快取消。我读过很多文章,总是建议在终止线程之前“清理”线程,老实说,我不知道“清理”是什么意思。但是,我认为我应该能够终止该线程 - 因为它所做的只是将图像的二进制数据发送到 TUMBLR api。如果提前取消请求也没关系,因为它也会取消 api 中的上传。
无论如何,这是我的主题:
Run Code Online (Sandbox Code Playgroud)class WorkThread(QtCore.QThread): def __init__(self): QtCore.QThread.__init__(self) global w w = WorkThread def __del__(slf): self.wait() def run(self): url = 'https://www.tumblr.com/api/write' files = os.listdir(directory) for file in files: file_path = os.path.join(directory + '\\' + file) file_path = str(file_path) if file_path[-3:] in ['bmp', 'gif', 'jpg', 'png', 'thm', …
我是 Qt 的新手,所以请原谅问题的简单性,但我对 Qt 线程有点困惑。假设我有 3 个线程:主默认 GUI 线程和我自己创建的 2 个线程(称为 WorkerThread)。我的每个 WorkerThreads 都继承自 QThread,并且是永久线程,它们经常被唤醒并向套接字发送数据并在 GUI 元素上发布状态。1) 允许 GUI 线程在 WorkerThread 线程可以使用的 WorkerThread 对象中设置数据的最佳方法是什么?2)允许WorkerThread将状态发送到GUI线程以显示给用户?3)允许两个WorkerThreads使用同一个socket?
从文档看来,当我创建一个 WorkerThread 对象时,它由创建线程拥有(除了作为新线程的 run 方法)。那么如何为新线程设置要执行的数据呢?新线程使用的所有数据都必须是全局的吗?例如,我希望 GUI 允许用户为每个 WorkerThread 选择在唤醒时发送的数据包类型。我假设我会在 WorkerThread 中放入一些由 GUI 线程发出信号的槽。当 WorkerThread 对象收到 SetPacketType 信号时,它将设置 run 方法在每次迭代时引用的成员变量。但在阅读文档后,我不确定这是否是正确的方法。如果 WorkerThread 对象由创建线程(在本例中为 GUI 线程)拥有,那么向它发送信号不会跨越线程边界,不是吗?
另外,跨线程共享套接字连接的正确技术是什么?
提前致谢。
我在递归模式下使用QReadWriteLock。
这段代码本身没有意义,但是我从这里出现的问题是:
lock->lockForWrite();
lock->lockForRead();
Run Code Online (Sandbox Code Playgroud)
lockForRead被阻止。请注意,这是在递归模式下。
我看到的方式是Write是一个“高级”锁,它允许我读写受保护的数据,而Read锁仅允许读取。
另外,我认为如果唯一的阅读器是同一位要求写锁定的读者,则不应阻止写锁定。
从qreadwritelock.cpp源代码中可以看到,没有尝试使其像我想要的那样工作。因此,这不是错误,而是我发现缺少的功能。
我的问题是,应该允许这种递归吗?这种实现会带来什么问题吗?它们将是什么?
我在使用Qt Threads和Connections时遇到了麻烦.我找到了关于这个主题的几个教程和讨论,我按照本教程创建了线程.但是我仍然遇到了问题,在线程上调用wait()永远不会返回并且UI冻结.
之前有一个类似的问题(第二个例子): 线程之间的Qt连接类型:为什么这有效?
在该问题的最后一次编辑中,作者提到他已经造成了僵局.我假设,我在我的应用程序中也这样做.但我仍然不明白,为什么会这样.阅读建议的文章并没有帮助我理解.我只是明白了,死锁可能发生,但我不知道,是什么导致它或在我的情况下.
我还创建了一个简化为核心问题的例子.找到这个问题底部的代码.
所以我的问题是:我的例子中死锁的原因是什么?是否有解决方案而不使连接成为直接连接?
我真的很感激任何提示.
谢谢!
编辑:
由于注释我试图通过信号发送停止请求,我在线程循环中添加了一个QCoreApplication :: processEvents()调用.但主要问题仍然是一样的.
EDIT2:
在考虑了更多关于事件循环之后,我找到了一个可接受的解决方案:
thread.requestStop();
// now instead of using wait(), we poll and keep the event loop alive
// polling is not nice, but if it does not take a very long time
// for the thread to finish, it is acceptable for me.
while (thread.isRunning())
{
// This ensures that the finished() signal
// will be processed by the thread object
QCoreApplication::processEvents();
} …Run Code Online (Sandbox Code Playgroud) 我使用的是 PySide 版本 1.2.2,它包装了 Qt v4.8 框架。QThread我面临的情况是,我必须在让我的应用程序等待我不再需要正常退出的情况(线程很可能会无限期地阻塞)和给无响应的线程一个宽限期(几秒钟)之间做出选择),然后调用QThread.terminate()它。尽管我希望可以,QThread但当底层线程仍在运行时,我不能让对象超出范围,因为这会抛出错误“QThread:线程仍在运行时被销毁”,并且几乎肯定会导致段错误。
请注意,我知道终止QThreads 是危险的并且强烈建议不要这样做。我只是想在这里探索我的选择。
然而,当我尝试终止线程时,我的应用程序崩溃并出现以下错误:
Python 致命错误:释放时该线程状态必须是当前状态
您可以通过复制/粘贴并运行以下代码自行尝试:
from PySide import QtCore, QtGui
class Looper(QtCore.QThread):
"""QThread that prints natural numbers, one by one to stdout."""
def __init__(self, *args, **kwargs):
super(Looper, self).__init__(*args, **kwargs)
self.setTerminationEnabled(True)
def run(self):
i = 0
while True:
self.msleep(100)
print(i)
i += 1
# Initialize and start a looper.
looper = Looper()
looper.start()
# Sleep main thread for 5 seconds.
QtCore.QThread.sleep(5)
# Terminate …Run Code Online (Sandbox Code Playgroud) 我在Qt5Application中有2个线程:
线程A:包含一堆QObject派生类对象
线程B:此Thread中的worker具有指向A中对象的所有指针
线程A有时可能非常繁忙,而线程B只在那里委托信号并管理其他一些东西.它从不写入任何这些对象,但我需要检查一些从A中的对象返回布尔值的getter函数.
in ThreadB:
if (objInThrA->isFinished()) { ... }
Run Code Online (Sandbox Code Playgroud)
isFinished()返回一个布尔值.
如果线程A真的忙于函数并且我在线程B中调用这些isFinished函数,那么我的线程B是否会停止,直到线程A完成它的工作,或者这会工作吗?
我正在尝试暂停 QThread 并恢复它。
所以,我在 QThread 中有一个 RFID 读取循环,我想在读取器获得 RFID 代码时暂停无限循环。之后,进行数据库检查。在检查结束时,我想恢复 RFID 读取循环以获取其他代码。
MVCE:
def main():
global Thread
app = QtGui.QApplication(sys.argv)
main = Main()
Thread = RFID_Thread()
Thread.rfid_event.connect(Main().on_event)
Thread.start()
sys.exit(app.exec_())
class Main(object):
def __init__(self):
self.accueil = MainWindow(self)
self.access = AccessWindow()
self.accueil.show()
def on_event(self, data):
# I WANT TO PAUSE THE QTHREAD HERE
###################################
# CHECKING DB & SHOWING UI #
###################################
# AND RESUME IT HERE
class RFID_Thread(QtCore.QThread):
rfid_event = pyqtSignal(str, name='rfid_event')
def run(self):
while 1:
ser = serial.Serial(port=Serial_Port, baudrate=Serial_Baudrate)
a …Run Code Online (Sandbox Code Playgroud) 我真的很难理解如何在 PyQt 中使用线程。我做了一个简单的例子来说明我想在用户界面中做什么。在下面的代码中,我希望用户输入股票行情(例如,您可以输入“bby”、“goog”或“v”)并绘制特定时期内股票的价值。问题是在更复杂的用户界面中,或者在很长一段时间内,用户界面在绘图更新时冻结。所以我制作了一个“绘图仪”类,当它收到某个信号时更新绘图(覆盖 Qthread.run 显然不是你做错的正确方法)。我想让这个“绘图仪”在主线程之外的另一个线程中运行。
一旦我取消注释线程,程序就会停止工作。我尝试移动新线程的启动以及“连接”,但没有任何效果。我认为即使在阅读了文档并查看了 Qt 网站上的示例之后,我仍然不太理解 Qthread 的工作原理。
如果您知道如何做到这一点,那将会有很大帮助!(我正在使用 Python 3.5 和 PyQt5)
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from matplotlib.axes._subplots import Axes
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import sys
from datetime import datetime, timedelta
import time
import quandl
class MyMplCanvas(FigureCanvas):
"""Ultimately, this is a QWidget (as well as a FigureCanvasAgg, etc.)."""
send_fig = pyqtSignal(Axes, str, name="send_fig")
def __init__(self, parent=None):
self.fig = Figure()
self.axes = self.fig.add_subplot(111)
# …Run Code Online (Sandbox Code Playgroud) 我使用的QThread使用阅读的QThread应如何使用扩展的讨论和通过继承是不正确的方法重写它的run方法后,一个工人对象。但是,在我打算使用的方法中,我需要传递一个附加的函数参数,该参数在启动线程并将工作器使用推送到线程时不可用moveToThread。该信息(参数)在按下按钮时可用,并传达有关要移动的对象的信息。
在我的代码的完整版中,有3个单独的控制器,用于3个单独的对象,您可以在下面找到一个最小的工作示例,以说明我尝试传递参数的内容。该代码也可以在pastebin上使用,感兴趣的行号为10-28、46-50和133-135。
到目前为止,我已经尝试在连接到worker中实际函数的行中使用lambda构造函数。那行self.thread.started.connect(self.obj.moveLeftIncrement)尝试使用slot,但是我不太了解它们。此外,尽管使用了QThread,但有时GUI仍然挂起,并且在程序退出后仍会出现错误,其中之一如下:
进程完成,退出代码-1073740791(0xC0000409)
我的问题如下:
from PySide2.QtCore import *
from PySide2.QtWidgets import *
from PySide2.QtGui import *
import sys
import time
class Worker(QObject):
finished = Signal(int)
@Slot(str)
def moveLeftIncrement(self, controller_name):
# controller_name = "Controller 1"
print("Controller name is ", controller_name)
if controller_name == "Controller 1":
print("Starting controller 1")
time.sleep(2)
print("Finishing sleep")
elif controller_name == "Controller 2":
print("Starting controller 2")
time.sleep(2)
print("Finishing sleep")
elif controller_name == "Controller 3": …Run Code Online (Sandbox Code Playgroud) qthread ×10
qt ×6
python ×5
c++ ×3
pyqt ×2
qt5 ×2
inheritance ×1
kill ×1
matplotlib ×1
mutex ×1
pyqt4 ×1
pyside ×1
pyside2 ×1
python-3.x ×1
qtcore ×1