lua - wxLua - 如何实现取消按钮?

标签 lua wxwidgets coroutine cancel-button

我有一个 wxLua Gui 应用程序,它有一个“运行”按钮。根据所选选项,运行可能需要很长时间,因此我想实现“取消”按钮/功能。但看起来 wxLua 中的所有内容都在一个 Gui 线程上运行,一旦你点击“运行”,按“取消”不会执行任何操作,运行总是会完成。

取消基本上将变量设置为 true,并且正在运行的进程会定期检查该变量。但“取消”按钮按下事件在运行时永远不会发生。

我从来没有使用过协同例程;如果运行过程定期产生“取消检查”过程,那么取消事件会发生吗?

或者还有其他方法吗?

最佳答案

(下面假设“运行”是指在同一进程中长时间运行的操作,并且使用 wxExecute 或 wxProcess 运行外部进程。)

“取消”事件不会被触发,因为通过执行运行逻辑,您没有给 UI 机会来处理点击事件。

为了避免阻塞 UI,您需要执行类似的操作。当您单击“运行”按钮时,围绕要运行的函数创建一个协同例程:

coro = coroutine.create(myLongRunningFunction)

此时您的运行事件已完成。然后,在 EVT_IDLE 事件中,只要该协程未完成,您就会恢复该协程。它看起来像这样:

if coro then -- only if there is a coroutine to work on
  local ok, res = coroutine.resume(coro, additional, parameters)
  -- your function either yielded or returned
  -- you may check ok to see if there was an error
  -- res can tell you how far you are in the process
  -- coro can return multiple values (just give them as parameters to yield)
  if coroutine.status(coro) == 'dead' then -- finished or stopped with error
    coro = nil
    -- do whatever you need to do knowing the process is completed
  end
end

只要您的进程未完成,您可能就需要请求更多 IDLE 事件,因为某些操作系统不会触发 IDLE 事件,除非触发了其他事件。假设您的处理程序具有 event 参数,您可以执行 event:RequestMore(true) 来请求更多 IDLE 事件 ( RequestMore )。

您的长时间运行的进程需要在正确的时间调用 coroutine.yield() (不能太短,因为您会浪费时间来回切换,也不能太长,否则用户会注意到 UI 中的延迟);您可能需要对此进行试验,但是基于计时器的调用之间间隔 100 毫秒左右的东西可能会起作用。

您可以像现在一样在 IDLE 事件处理程序或长时间运行的函数中检查 Cancel 值。我描述的逻辑将使您的应用程序 UI 有机会按照您的预期处理取消事件。

关于lua - wxLua - 如何实现取消按钮?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12412239/

相关文章:

Kotlin 协程:在 Sequence::map 中调用 Deferred::await

lua - 从 C 回调闭包时 GC 中的 MemFault

Lua:以不区分大小写的方式合并2个字符串集合

c++ - wxSlider点击鼠标时如何设置步长?

wxpython - wxWidgets 自定义窗口形状 (PNG)

kotlin - Kotlin 挂起功能是否在单独的线程上运行?

lua - 覆盖lua中的断言

c++ - 当我的 lua 代码抛出错误时,为什么我无法捕获 luabind::error 异常?

c++ - 适用于 C++ 的 IDE 和对 wxWidgets 的支持

c++ - 无堆栈协程与有堆栈协程有何不同?