我在理解回调时遇到了一些麻烦。我有以下用例:
从我的gui我开始一个名为videoDown的新线程(这是它自己的类)。从这个线程我想把数据推回到gui,我已经实现了回调系统。但要更新GUI我需要在GUI线程而不是我当前所在的线程(这是videoDown线程)。
我启动线程的代码(类下载器):
def download_single(self, json_data):
form_data = json.loads(json_data)
print self.app
url = form_data["name"]
dt = form_data["dt"] # Download type is audio or video
videoDown = videoDownload(url, dt, self.dd,callback=self.cb,callback_args=("hello", "world",self.app))
videoDown.start()
videoDownload thread:
class videoDownload(threading.Thread):
def __init__(self,url, dt, dd,callback=None, callback_args=None, *args, **kwargs):
threading.Thread.__init__(self)
self.callback = callback
self.url = url
self.dt = dt
self.dd = dd
self.callback_args = callback_args
if self.callback is not None:
self.callback(*self.callback_args)
def run(self):
if self.url.__contains__("https://www.youtube.com/watch?v="):
if self.dt == 'audio':
self._downloadVid(self.url, vid=False)
else:
self._downloadVid(self.url, vid=True)
else:
print "Incorrect url"
def _downloadVid(self, url, vid=False, order_reverse=False, vinName=None):
video = pafy.new(url)
if self.callback is not None: //<--CALLBACK IN HERE
self.callback(*self.callback_args)
streams = video.allstreams
for stream in streams:
print stream
print video
name = u''.join(video.title).encode('utf8')
name = re.sub("[<>:\"/\\|?*]", "", name)
if not vid:
file = video.getbestaudio()
else:
file = video.getbest()
if (order_reverse):
file.download(self.dd + vinName + name + ".mp4", quiet=False, callback=self.mycb)
else:
file.download(self.dd + name + ".mp4", quiet=False, callback=self.mycb)
回调(也在类Downloader中):
def cb(self,param1, param2,param3):
print threading.current_thread()
我是如何实现它的,所以我可以将当前线程设置为此视频下载线程时,将我的视频下载线程中的数据返回给gui线程。
我需要改变什么,我几个小时都在苦苦挣扎。
〜问候
答案 0 :(得分:1)
也许使用Queue而不是回调。初始化主线程中的队列,将对象传递给下载线程,并调用Queue对象上的get()来阻塞,直到项目传递给它。
stdafx.h
在videoDownload对象中,通过Queue
将数据传回主线程q = Queue.Queue()
d = ("hello", "world", self.app)
videoDown = videoDownload(url, dt, self.dd, queue=q, data=d)
returned_data = q.get()
答案 1 :(得分:1)
来自luke的大量帮助。我想出了以下答案。
在我的javascript中,我创建了以下功能:
function start() {
Downloader.trydasd(); //ignore the nameconvention. We all try sometimes
setTimeout(start, 3000);
}
start();
这是在python中实现的,如下所示:
@htmlPy.Slot()
def trydasd(self):
if not self.q.empty():
print self.q.get(block=False)
之后我改变了我的init来创建这样的队列:
def __init__(self, app):
super(Downloader, self).__init__()
# Initialize the class here, if required.
self.app = app
self.q = Queue.Queue()
之后我将download_single函数更改为:
def download_single(self, json_data):
form_data = json.loads(json_data)
print self.app
url = form_data["name"]
dt = form_data["dt"] # Download type is audio or video
d = ("hello", "world", self.app)
videoDown = videoDownload(url, dt, self.dd, queue=self.q, data=d)
videoDown.start()
最后我的下载主题是:
class videoDownload(threading.Thread):
def __init__(self,url, dt, dd,queue=None,data=None, *args, **kwargs):
threading.Thread.__init__(self)
self.queue = queue
self.data = data
self.url = url
self.dt = dt
self.dd = dd
def run(self):
if self.url.__contains__("https://www.youtube.com/watch?v="):
if self.dt == 'audio':
self._downloadVid(self.url, vid=False)
else:
self._downloadVid(self.url, vid=True)
else:
print "Incorrect url"
def _downloadVid(self, url, vid=False, order_reverse=False, vinName=None):
video = pafy.new(url)
if self.queue and self.data:
self.queue.put(video)
name = u''.join(video.title).encode('utf8')
name = re.sub("[<>:\"/\\|?*]", "", name)
if not vid:
file = video.getbestaudio()
else:
file = video.getbest()
if (order_reverse):
file.download(self.dd + vinName + name + ".mp4", quiet=False, callback=self.mycb)
else:
file.download(self.dd + name + ".mp4", quiet=False, callback=self.mycb)
这解决了我的问题,任何其他方式都不起作用,并会阻止用户界面。
非常感谢卢克!