wxPython wx.CallAfter-如何让它立即执行?

wxPython wx.CallAfter-如何让它立即执行?,python,events,wxpython,Python,Events,Wxpython,当我使用wx.CallAfter执行一个函数时,其中设置了一个变量。我希望能够在下一行中获得该变量的值,但是CallAfter似乎会在以后多次执行该函数。我想它会把它推到稍后处理的队列中或者其他什么。。。有没有办法让队列立即得到处理 这是wx.CallAfter的代码: def CallAfter(callableObj, *args, **kw): """ Call the specified function after the current and pending eve

当我使用wx.CallAfter执行一个函数时,其中设置了一个变量。我希望能够在下一行中获得该变量的值,但是CallAfter似乎会在以后多次执行该函数。我想它会把它推到稍后处理的队列中或者其他什么。。。有没有办法让队列立即得到处理

这是wx.CallAfter的代码:

def CallAfter(callableObj, *args, **kw):
    """
    Call the specified function after the current and pending event
    handlers have been completed.  This is also good for making GUI
    method calls from non-GUI threads.  Any extra positional or
    keyword args are passed on to the callable when it is called.

    :see: `wx.CallLater`
    """
    assert callable(callableObj), "callableObj is not callable"
    app = wx.GetApp()
    assert app is not None, 'No wx.App created yet'

    if not hasattr(app, "_CallAfterId"):
        app._CallAfterId = wx.NewEventType()
        app.Connect(-1, -1, app._CallAfterId,
                    lambda event: event.callable(*event.args, **event.kw) )
    evt = wx.PyEvent()
    evt.SetEventType(app._CallAfterId)
    evt.callable = callableObj
    evt.args = args
    evt.kw = kw
    wx.PostEvent(app, evt)
我的假设是wx.PostEvent将“evt”放在“app”中的某个内部容器中,在某个点上,容器被迭代,所有元素都执行了“callable”之类的操作?因此,基本上我需要立即执行此操作,但我找不到任何类似于“wx.ForceEventProcessing()”或“wx.FlushEventsQueue”的内容


我尝试在定义方法的面板中调用self.Update(),但这只是阻止了应用程序,它停止了响应。

你尝试过谷歌吗?我做到了,我有了一些想法。请参见以下线程:


请尝试wx.WakeUpIdle()wx.GetApp().ProcessIdle()。我还注意到在中,wx.App有一个ProcessPendingEvents方法,因此您也可以尝试wx.Getapp().ProcessPendingEvents()

正如您所猜测的
wx.CallAfter
将调用信息添加到队列中(挂起事件队列,下次清空事件队列时在GUI线程中处理),然后立即返回。换句话说,它是一个“触发并忘记”函数调用

如果你需要得到被调用函数的结果,有几种方法可以采用。一种是延迟结果模式,基本上你会得到一个结果对象,在调用函数后,它会收到函数调用的结果,调用代码会在发生这种情况时收到通知这在
wx.lib.delayedresult
中,可能在不同的地方可以找到此模式的其他实现。这种方法的好处是调用线程不必停止等待结果,并且可以继续处理其他需要的事情


在我看来,另一种非常好的方法是
wxAnyThread
,可以在中找到。这个模块提供了一个装饰器,允许从任何线程调用方法,就像普通函数调用一样,但是当从GUI线程以外的其他线程调用方法时,它将使用
wx.CallAfter
-样的处理来拥有该函数在UI线程中调用,然后等待结果,并在收到结果时将其返回给调用方。因此,尽管在处理UI事件和调用函数时调用线程被阻塞,但在调用端使用起来更简单,并降低了复杂性。

hmm,现在调用
wx.GetApp().ProcessPendingEvents()之后
执行wx调用且我传递给wx.CallAfter的任何函数都会导致线程死亡,而不会留下任何错误消息或引发任何异常。可能是因为您从错误的线程调用了
ProcessPendingEvents
。这会产生相同的问题(以及更多问题)从错误的线程调用函数。
wx.PostEvent
已经调用了
WakeUpIdle
。它基本上只是在事件队列中添加了一个本机NULL事件,因此如果它已经是空的,它一定会及时地再次“变为空”。@RobinDunn-我不知道这一点。这太好了!调用wx.GetApp().ProcessPendingEvents()在wx.CallAfter为我解决了类似的问题之后,我认为如果您对线程处理感到满意,那么就永远不需要wx.CallAfter。@user2963623在我传递给wx.CallAfter的函数中进行wx调用之后,您知道什么会导致应用程序完全挂起吗?它不会引发异常,也不会输出警告,也不会设置断点点击它。它只是挂断了应用程序。这是指您之前关于使用
msvcrt.getch()
注册按键的问题吗?
msvcrt.getch()
似乎不适用于PyDev:,但我当前所做的工作习惯于工作(在移动到另一个线程并使用
wx.CallAfter()
之前)。但是是的,它挂起的方式与
msvcrt.getch()挂起的方式相同,并且在控制台或异常中没有留下警告或错误消息。嗯,我注意到在停止调试后,PyDev会告诉我线程的退出代码,其中
wx.CallAfter()调用了
,is
-1
我尝试了wxAnyThread,我用
@anythread
修饰了我的方法,然后创建了一个线程:
worker\u thread=thread(target=self.WxCallsMethod,name=“worker thread”)worker\u thread.start()
发生的事情是,WxCallsMethod从未被调用,其开始处的断点没有被命中。如果我删除@anythread,它会命中断点,但当它执行wx调用时,它当然会崩溃。我尝试将@anythread方法放入非@anythread方法中,当我使用非anythread方法启动线程时,它会命中断点,但在@anythread one上再次失败…您需要提供一个小的、可运行的代码示例。@Bogomil您绝对不应该在线程的目标函数上使用
@anythread
,但您可以在它调用的任何需要与GUI交互的函数上使用它。