我有一个 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/