app.thread - 并发/协程 API
后台任务和并发控制。
方法
app.thread.create(func)
创建并启动后台协程。
参数:
func(function) - 要在后台执行的函数
返回值: number - 协程 ID
local tid = app.thread.create(function()
-- 耗时操作(如 shell 命令、HTTP 请求)
local result = app.shell.execute("find ~/Downloads -name '*.zip'")
return result
end)
app.thread.wait(tid, timeout?)
等待协程完成并获取结果。
参数:
tid(number) - 协程 IDtimeout(number, 可选) - 超时时间(毫秒)
返回值: any - 协程返回值
local tid = app.thread.create(function()
app.thread.sleep(2000) -- 2秒
return "完成"
end)
local result = app.thread.wait(tid) -- 阻塞等待
app.log.info(result) -- "完成"
-- 带超时
local result = app.thread.wait(tid, 5000) -- 最多等5秒
app.thread.waitAll(tids, timeout?)
等待所有协程完成。
参数:
tids(table) - 协程 ID 数组timeout(number, 可选) - 超时时间(毫秒)
返回值: table - 结果数组(与输入顺序对应)
local tids = {}
for i, file in ipairs(files) do
tids[i] = app.thread.create(function()
return processFile(file)
end)
end
local results = app.thread.waitAll(tids)
app.thread.waitAny(tids, timeout?)
等待任意一个协程完成。
参数:
tids(table) - 协程 ID 数组timeout(number, 可选) - 超时时间(毫秒)
返回值: table - {tid = 完成的协程ID, result = 返回值}
local tid1 = app.thread.create(function() return fetchFromServer1() end)
local tid2 = app.thread.create(function() return fetchFromServer2() end)
-- 使用最先返回的结果
local first = app.thread.waitAny({tid1, tid2})
app.log.info("协程 " .. first.tid .. " 先完成")
app.thread.cancel(tid)
取消协程。
参数:
tid(number) - 协程 ID
返回值: boolean - 是否成功取消
local tid = app.thread.create(function()
-- 长时间任务
end)
-- 超时后取消
app.thread.sleep(5000)
if app.thread.status(tid) == "running" then
app.thread.cancel(tid)
end
注意:取消只能在协程挂起时生效。正在执行的 I/O 操作(如 shell 命令)无法中途取消。
app.thread.cancelAll()
取消所有协程。
-- 用户点击取消时,停止所有后台任务
app.thread.cancelAll()
app.thread.status(tid)
获取协程状态。
参数:
tid(number) - 协程 ID
返回值: string - 状态
| 状态 | 说明 |
|---|---|
pending |
等待执行 |
running |
执行中 |
suspended |
挂起(等待 I/O) |
completed |
已完成 |
failed |
执行失败 |
cancelled |
已取消 |
local status = app.thread.status(tid)
if status == "completed" then
local result = app.thread.wait(tid)
end
app.thread.sleep(ms)
暂停当前协程执行。
参数:
ms(number) - 暂停毫秒数
app.thread.create(function()
app.log.info("开始")
app.thread.sleep(2000) -- 暂停2秒
app.log.info("继续")
end)
app.thread.activeCount()
获取当前活跃的协程数量。
返回值: number
local count = app.thread.activeCount()
app.log.info("活跃协程: " .. count)
示例
并行处理文件
function MyPlugin:handleBatchProcess(context)
local files = context.selectedFiles
app.progress.show("处理中", {total = #files})
-- 创建所有协程
local tids = {}
for i, file in ipairs(files) do
tids[i] = app.thread.create(function()
return self:processFile(file)
end)
end
-- 等待所有完成
local results = app.thread.waitAll(tids)
app.progress.hide()
-- 统计结果
local success = 0
for _, r in ipairs(results) do
if r then success = success + 1 end
end
app.notification.show("完成", "成功处理 " .. success .. "/" .. #files .. " 个文件")
end
带超时的网络请求
function MyPlugin:fetchWithTimeout(url, timeout)
local tid = app.thread.create(function()
return app.http.get(url)
end)
local result = app.thread.wait(tid, timeout or 30000)
if app.thread.status(tid) ~= "completed" then
app.thread.cancel(tid)
return nil, "请求超时"
end
return result
end
竞速模式(使用最快的结果)
function MyPlugin:fetchFromMirrors(mirrors)
local tids = {}
for i, url in ipairs(mirrors) do
tids[i] = app.thread.create(function()
return app.http.get(url)
end)
end
-- 使用最先返回的结果
local first = app.thread.waitAny(tids)
-- 取消其他请求
for _, tid in ipairs(tids) do
if app.thread.status(tid) == "running" then
app.thread.cancel(tid)
end
end
return first.result
end
注意事项
- 适用场景:协程适合 I/O 密集型任务(shell 命令、HTTP 请求、文件操作),不适合 CPU 密集型计算
- 并发数量:建议同时运行的协程不超过 8 个,避免资源竞争
- 取消限制:正在执行的 I/O 操作无法立即取消,只能在操作完成后检测取消状态
- 错误处理:协程内的错误会导致状态变为
failed,使用app.thread.wait()获取结果时会返回nil