模块threading提供了多线程相关操作,event可以帮助我们实现线程间通信
threading.Event()可以产生一个event对象,并带一个默认值为False的标志位,通过方法set()可以设置为True;
wait(timeout)用于堵塞线程,可以设置延迟时间,当event标志为False时,线程被阻塞,直至标志位被set()为True;
clear()用于清除标志位,使之为False;isSet()判断标志位是否为True
注意:
线程是不能被停止、暂停、恢复、中断的,这里通过wait阻塞,可以实现暂停、退出的效果,必须在循环中使用。一旦该线程通过wait()方法进入等待状态,直到另一个线程调用该Event的set()方法将内置标志设置为True时,该Event会通知所有等待状态的线程恢复运行。而当我们再将内置标志设置为False时,会在设置后的下一次调用wait()方法后才阻塞线程。
下面我们举例来介绍下:
1.自定义MyThread继承Thread类,传入的log_ctrl参数是Frame中的文本框,此处先不用理会
2.然后我们定义Event对象,并设置标志位为True
3.在线程活动方法run()中,循环打印1-10,其中通过self.singal.wait()阻塞线程,每次循环到此处时,会判断该线程对象标志位,False则阻塞以下活动
4.定义pause和restart函数(通过设置标志位来控制)
class MyThread(threading.Thread):
def __init__(self, log_ctrl):
super().__init__()
self.log_ctrl = log_ctrl
# 定义event对象,并使用set()设置标志位为True
self.singal = threading.Event()
self.singal.set()
def run(self):
self.log_ctrl.AppendText("start:\n")
for i in range(1, 11):
self.singal.wait()
self.log_ctrl.AppendText("第%d行\n" % i)
time.sleep(1)
def pause(self):
self.log_ctrl.AppendText("pause\n")
self.singal.clear()
def restart(self):
self.log_ctrl.AppendText("continue\n")
self.singal.set()
为方便演示,我们加入图形化来看下效果
同理,对于退出线程,我们可以另设一个属性
self.__running = threading.Event()
并通过while来控制,达到退出的效果
def run(self): while self.__running.isSet(): self.__flag.wait() print time.time() time.sleep(1) def stop(self): self.__flag.set() self.__running.clear()
当退出线程时,先恢复暂停的线程(没有暂停的话可以忽略),再设置self.__running标志位为false,使之退出
以下是完整代码(不包含线程退出)
import threading
import wx
import time
class MyThread(threading.Thread):
def __init__(self, log_ctrl):
super().__init__()
self.log_ctrl = log_ctrl
self.singal = threading.Event()
self.singal.set()
def run(self):
self.log_ctrl.AppendText("start:\n")
for i in range(1, 11):
self.singal.wait()
self.log_ctrl.AppendText("第%d行\n" % i)
time.sleep(1)
def pause(self):
self.log_ctrl.AppendText("pause\n")
self.singal.clear()
def restart(self):
self.log_ctrl.AppendText("continue\n")
self.singal.set()
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="test")
self.panel = wx.Panel(self)
self.button1 = wx.Button(self.panel, label="启动", pos=(30, 0))
self.button2 = wx.Button(self.panel, label="暂停", pos=(150, 0))
self.button3 = wx.Button(self.panel, label="继续", pos=(270, 0))
self.thread = None
self.Bind(wx.EVT_BUTTON, self.button1_click, self.button1)
self.Bind(wx.EVT_BUTTON, self.button2_click, self.button2)
self.Bind(wx.EVT_BUTTON, self.button3_click, self.button3)
self.log_ctrl = wx.TextCtrl(self.panel, pos=(20, 40), size=(350, 160), style=wx.TE_MULTILINE)
def button1_click(self, event):
self.thread = MyThread(self.log_ctrl)
self.thread.start()
def button2_click(self, event):
self.thread.pause()
def button3_click(self, event):
self.thread.restart()
if __name__ == '__main__':
app = wx.App()
frame1 = MyFrame()
frame1.Show()
app.MainLoop()