`
marlonyao
  • 浏览: 252716 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

wxpython中工作线程与主线程交互

阅读更多
在wxpython中,像其它GUI框架一样,如果要进行耗时很长的任务,需要将该任务放在工作线程中运行,以保证程序的响应性。工作线程可能会需要与主线程进行交互。这可以分为两种情况:一是工作线程只是向主线程单向通知工作进行的状态,比如任务完成进度,并不要求主线程回应。第二种情况是工作线程要调用主线程的方法,并且要求其返回,例如工作线程运行中需要弹出对话框让用户输入必要的信息(在wxpython中,显示对话框必须在主线程中进行)。

对于第一种情况,wxwiki已经谈了很多了,一种是工作进行使用wx.CallAfter主要调用主线程的方法,一种是工作线程发布事件(也是利用CallAfter),主线程监听该事件。第一种方法用起来要简单一些,但不如第二种方法灵活。对于第二种情况,wxwiki却很少谈到,网上也很少谈到其解决方法。不能使用CallAfter的原因在于CallAfter是异步调用,它只是将调用放在事件队列中,调用就返回了。如果我们想要等待调用在主线程中执行完毕再返回,就得使用别的方法。在Swing中存在InvokeAndWait就是为了达到此目的,在wxpython却不存在这样的方法,所幸很容易使用python的线程类Event达到类似的效果。

import wx
import threading
def call_and_wait(target, *args, **kwargs):
	if wx.Thread_IsMain():
		return target(*args, **kwargs)
	else:
		context = {}
		context['event'] = threading.Event()
		wx.CallAfter(call_in_mainthread, context, target, *args, **kwargs)
		context['event'].wait()
		return context['result']

def call_in_mainthread(context, target, *args, **kwargs):
	context['result'] = target(*args, **kwargs)
	context['event'].set()


主要思想是在工作线程创建一个Event对象,然后利用CallAfter放在主线程中去调用,工作线程调用event.wait()开始等待,当主线程执行完调用之后,设置event的状态,这样工作线程开始继续运行。下面是使用这个方法的一个例子:

class WorkThread(Thread):
	def run():
		# ...
		call_and_wait(ShowSomeDialog)

def ShowSomeDialog():
	# display some dialog
	dlg = UserPassDialg(None)
	if dlg.ShowModel() == wx.ID_OK:
		return (dlg.Username, dlg.Password)
	else:
		return None


call_and_wait调用很别扭,利用decorator我们可以取消该方法的调用,取而代之我们把它的调用放到decorator去做。

def mainthread(func, *args, **kwargs):
	'''ensure func invoked in main thread'''
	def _func():
		return call_and_wait(func, *args, **kwargs)
	return _func


这样我们可以将前面的例子改写成:

class WorkThread(Thread):
	def run():
		# ...
		ShowSomeDialog()

@mainthread
def ShowSomeDialog():
	# display some dialog
	dlg = UserPassDialg(None)
	if dlg.ShowModel() == wx.ID_OK:
		return (dlg.Username, dlg.Password)
	else:
		return None


似乎上面的代码并没有简洁多少,但是如果碰到需要大量调用主线程的方法时候,使用decorator可以避免创建许多一次性的方法。例如,在应用使用sqlite的情况下,由于sqlite只能单线程使用,所以也不能在工作线程中调用sqlite方法,通常的方法就是将所有sqlite调用都放到主线程中去做。

@mainthread
def get_account(id):
	#....

@mainthread
def save_account(account):
	#...

# more sqlite methods

分享到:
评论

相关推荐

    Python GUI制作实例 wxPython使用多线程 防假死含wxFormBuilder的文件及源码.rar

    在GUI应用中,主线程负责更新界面,而其他线程可以执行耗时操作。这样,即使后台任务在运行,用户仍能继续与界面交互。在这个实例中,`ebom2.py`可能利用了多线程技术来防止程序在执行某些操作时阻塞用户界面。 `...

    多线程进度条(事件触发)

    主线程通常负责用户界面的交互,而额外的线程则处理后台任务,如数据加载或计算。在C#中,我们可以使用`System.Threading`命名空间中的`Thread`类或者`Task`类来创建新的线程。`Task`类更现代化,支持异步编程模型,...

    线程遍历文件下文件

    Python的`Queue`模块可以实现线程间的同步和通信,遍历线程将结果放入队列,主线程从队列中取出并更新界面。 6. **异常处理**: 文件系统操作可能会遇到各种错误,如权限问题、文件不存在等,因此需要捕获并处理...

    python wxpython 实现界面跳转功能

    这样,当用户触发特定事件(如点击按钮)时,我们可以在新的线程中关闭当前窗口,并在主线程中打开新的窗口,以实现平滑的界面过渡。 以下是一个简化的示例代码,展示了如何在wxPython中实现界面跳转: ```python ...

    简单python抽奖界面

    此时,可以利用Python的`threading`模块创建子线程来执行抽奖逻辑,主线程则继续负责界面更新,确保界面的流畅性。 8. **异常处理**:为了保证程序的稳定性和容错性,良好的编程习惯是添加异常处理代码,捕获并处理...

    python监控服务停止并启动

    主线程负责展示GUI,而另一个线程则定期检查服务状态,确保不会因为长时间阻塞主线程而影响用户界面的响应。 7. **异常处理**: 在处理系统服务时,可能会遇到各种错误,如权限问题、服务不存在等。因此,良好的异常...

    python 桌面宠物源码

    主线程负责显示和交互,而子线程则处理后台任务,避免阻塞用户界面。 5. **音频和视频支持**: 高级的桌面宠物可能需要播放音频或视频。Python 可以通过库如 pygame 或 moviepy 来处理音频和视频。pygame 提供了...

    gui管理系统gui管理系统

    主线程负责处理用户界面,后台线程则处理耗时任务,避免了用户界面的冻结。 6. **错误处理和调试**:GUI管理系统需要考虑异常处理和用户体验,如弹出友好的错误提示框,提供清晰的错误日志,便于开发者定位和解决...

    abcdefghijklmn

    主线程负责用户的交互,而另一个线程则负责不断地更新时钟的显示,确保时针、分针和秒针的动态转动。 3. **图形用户界面(GUI)设计**:时钟的界面需要创建一个窗口,显示时钟的表盘和三根指针。这可能涉及使用GUI...

    Python-InstantLyrics显示当前正在播放的Spotify歌曲或任何歌曲的歌词

    3. **多线程**:为了保证用户界面的响应性,Python-InstantLyrics可能使用了多线程技术,将歌词获取和显示任务放在后台运行,避免阻塞主线程。 4. **GUI编程**:可能使用了Tkinter、PyQt或wxPython等Python GUI库来...

    GUI-3.zip_源码

    1. 多线程:在GUI应用中,为了保持界面的响应性,通常会将耗时操作放在后台线程执行,避免阻塞主线程。这涉及到线程同步和通信,如信号量、条件变量、队列等。 2. 自定义控件:除了标准的GUI组件,有时需要创建...

    进程通信源代码 实现图形界面

    主线程负责处理用户交互,而其他线程则执行耗时的计算任务,两者通过进程通信机制交换数据。 2. **异步编程**:为了防止阻塞UI,进程通信通常与异步操作结合,如回调函数、事件监听器或协程。 3. **信号与槽**:在...

    进度条应用源码(2008)版.rar

    通过在后台线程执行耗时任务,主线程可以继续处理用户交互,从而提高应用的用户体验。 7. **自定义样式**:为了适应不同的应用风格,进度条的外观和颜色都可以自定义。开发者可以根据需要调整进度条的宽高、边框、...

    用python编写的 背单字 软件,不错!!

    这得益于Python的多线程特性,开发者可能创建了一个后台线程来执行单词复习任务,而主线程则保持用户界面的正常响应,确保了用户可以边背单词边进行其他活动。 3. **单词学习算法**: 背单词软件的核心功能是根据...

    python时钟(高分课后作业)

    主线程负责显示时钟,而其他线程可以处理额外的计算或I/O操作。 9. **定时器**: - 而不是使用无限循环,你还可以利用`threading.Timer`来周期性地更新时间,这在创建定时任务或避免阻塞主线程时特别有用。 通过...

    完整版读取文件并显示进度.rar

    主线程负责UI更新,而另一个线程负责文件读取操作。这样即使文件读取过程耗时较长,也不会阻塞用户界面。在Python中,可以使用`threading`模块来创建和管理线程。 5. **事件驱动编程**:另一种处理方式是使用事件...

    类似任务管理器中的动态曲线绘制

    6. **多线程/进程**:为了不阻塞主线程,数据获取和UI更新可能需要在单独的线程或进程中执行,特别是在实时性要求较高的场景。 7. **性能优化**:考虑到实时性和效率,优化数据读取速度和绘制效率是必要的。例如,...

    TCP.zip_socket通信

    3. 异步处理:为了确保用户界面的响应性,需要在后台线程中处理网络通信,避免阻塞主线程。 4. 安全考虑:考虑使用SSL/TLS加密通信,防止数据被窃取。 此外,为了调试和优化,开发者通常会利用抓包工具(如...

    python手势识别GUI系统

    6. **多线程/异步处理**:为了确保流畅的用户体验,视频流的捕获和处理通常在后台线程进行,而GUI的更新则在主线程中。这样可以避免程序因处理视频而阻塞用户界面。 7. **错误处理和调试**:在实际应用中,必须考虑...

Global site tag (gtag.js) - Google Analytics