耗时活别卡界面:task 与 thread
为什么需要异步
Lua 是顺序执行的:脚本停在网络请求上,界面就跟着冻住。把耗时活挪到后台跑,跑完再回来更新界面——这就是 task 和 thread 存在的意义。两者怎么选:
| 方案 | 适合 | 一句话 |
|---|---|---|
| task | 一次性任务 | 跑完就结束,结果回传主线程 |
| thread | 常驻线程 | 一直活着,随时通信 |
task:跑完就回来
require "import"
func = [[
require "import"
a, b = ...
return a + b
]]
task(func, 1, 2, print)
读法:func 是一段以字符串形式写的代码(双中括号包多行字符串),task 把它丢到后台执行,1, 2 作为参数传进去(代码里用 a, b = ... 接),最后 print 是回调函数——任务返回值会传给它,而且回调是在主线程执行的,可以直接更新界面。
注意参数类型限制:布尔、数值、字符串、Java 对象都能传,Lua 表不行。
thread:常驻的对话
t = thread(func, 1, 2) -- 起一个线程
call(t, "add") -- 调线程里的 add 函数
set(t, "count", 5) -- 设线程里的变量
线程跟主线程是两个世界,通信走 call(调对方函数)与 set(设对方变量)两个方向;线程要结束必须调 quit,否则一直挂着。多数小工具用 task 就够,thread 留给真正需要持续后台活动的场景(后台轮询、长连接之类)。
一个最常见的组合
「http 请求 + task」是掌上脚本的高频组合——界面点一下,后台发请求,回调用结果更新界面:
task([[require "import" import "http" return http.get("网址写这里")]], nil, function(body)
print(body)
end)
参数不够用时补 nil 占位。把这段跑通,你写的脚本就已经是个像样的联网小应用了。数据回来后要拆 JSON,回网络请求。