【问题标题】:How can I stop a thread in wxpython?如何停止 wxpython 中的线程?
【发布时间】:2016-03-22 10:46:42
【问题描述】:

[问题] 我想停止调用函数的线程。

[代码]

import wx
app = wx.App(redirect=False)
top = wx.Frame(None)
sizer = wx.GridBagSizer()
import threading
shutdown_event = threading.Event()
def testFunction(event):
    while not shutdown_event.is_set():
        import time
        for i in range(2):
            print ('win','r')
            time.sleep (0.5)
            print ('abc')
            time.sleep (0.5)
            print ('enter')
            time.sleep (0.5)
            print 'sleep'
            time.sleep (3)


def startThread(event):
    import threading
    th = threading.Thread(target=testFunction, args=(event,))
    th.start()


def stopThread(event):
    shutdown_event.set()



addButton = wx.Button( top, -1, "Start", style=wx.BU_EXACTFIT )
sizer.Add(addButton, (6, 8), (2, 14), wx.EXPAND)
stopButton = wx.Button( top, -1, "Stop", style=wx.BU_EXACTFIT )
sizer.Add(stopButton, (8, 9), (2, 14), wx.EXPAND)
top.Bind(wx.EVT_BUTTON, startThread, addButton)
top.Bind(wx.EVT_BUTTON, stopThread, stopButton)
top.Sizer = sizer
top.Sizer.Fit(top)
top.Show()
app.MainLoop()

[当前] 如果我点击“停止”按钮,什么都不会发生。

[渴望] 如果我点击“停止”按钮,函数“testFunction”应该会停止。

【问题讨论】:

    标签: python multithreading wxpython wxwidgets


    【解决方案1】:

    是的,它正在停止,问题是它没有被中断,它一直在运行,直到脚本的两次迭代都完成,然后检查 while condition,然后它停止。

    import wx
    app = wx.App(redirect=False)
    top = wx.Frame(None)
    sizer = wx.GridBagSizer()
    import threading
    shutdown_event = threading.Event()
    def testFunction(event):
        while not shutdown_event.is_set():
            import time
            for i in range(2):
                print u"Iteración {}".format(i)
                if shutdown_event.is_set():
                    break;
                print ('win','r')
                time.sleep (0.1)
                if shutdown_event.is_set():
                    break;
                print ('abc')
                time.sleep (0.1)
                if shutdown_event.is_set():
                    break;
                print ('enter')
                time.sleep (0.1)
                if shutdown_event.is_set():
                    break;
                print 'sleep'
                time.sleep (0.5)
            print u"Fin de ejecución\n\n"
        print u"Se detuvo la ejecución.\n\n"
    
    
    def startThread(event):
        import threading
        th = threading.Thread(target=testFunction, args=(event,))
        th.start()
    
    
    def stopThread(event):
        shutdown_event.set()
    
    
    addButton = wx.Button( top, -1, "Start", style=wx.BU_EXACTFIT )
    sizer.Add(addButton, (6, 8), (2, 14), wx.EXPAND)
    stopButton = wx.Button( top, -1, "Stop", style=wx.BU_EXACTFIT )
    sizer.Add(stopButton, (8, 9), (2, 14), wx.EXPAND)
    top.Bind(wx.EVT_BUTTON, startThread, addButton)
    top.Bind(wx.EVT_BUTTON, stopThread, stopButton)
    top.Sizer = sizer
    top.Sizer.Fit(top)
    top.Show()
    app.MainLoop()
    

    【讨论】:

    • 我明白你的意思。我的目标是在我单击停止 btn 时立即停止该功能。换句话说,如果函数总共有5个步骤,当函数在第3步时我点击“停止”,那么第4步不应该再执行了。
    • 那么你必须在每一步之前添加'breakcontinue
    • [plus1] 因为我懒得去查找如何最好地打破while 循环:D
    【解决方案2】:

    如果你想在你的线程中有更精细的粒度,你必须实现它。使用类似这样的方法,使用 yield 语句将生成器语句中的不同步骤分开:

    def testFunction(event):
        def inner_gen():
            print ('win','r')
            time.sleep (0.5)
            yield
            print ('abc')
            time.sleep (0.5)
            yield
            print ('enter')
            time.sleep (0.5)
            yield
            print 'sleep'
            time.sleep (3)
            yield
    
        while True:
            for _ in range(2):
                for _ in inner_gen():
                    if shutdown_event.is_set():
                        shutdown_event.clear()
                        return
    

    【讨论】: