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) - 协程 ID
  • timeout (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

注意事项

  1. 适用场景:协程适合 I/O 密集型任务(shell 命令、HTTP 请求、文件操作),不适合 CPU 密集型计算
  2. 并发数量:建议同时运行的协程不超过 8 个,避免资源竞争
  3. 取消限制:正在执行的 I/O 操作无法立即取消,只能在操作完成后检测取消状态
  4. 错误处理:协程内的错误会导致状态变为 failed,使用 app.thread.wait() 获取结果时会返回 nil
开发者文档
使用帮助
使用说明 脚本菜单 常见问题
脚本开发
开发指南
插件开发
快速开始 开发指南 示例插件
API 参考
概览 API 查询 插件信息 日志 Finder 上下文 插件设置 国际化
UI 与交互
对话框 进度条 系统通知 选择器 WebView 状态栏 Dock
文件与路径
文件操作 路径工具 Finder 操作 废纸篓 扩展属性 元数据 文件监听
数据格式
JSON Plist CSV XML PDF 图片
文本与编码
字符串 正则表达式 日期时间 颜色 加密编码
系统
Shell 命令 进程管理 应用管理 系统信息 AppleScript 快捷指令
系统信息
网络信息 电源/电池 屏幕/外观 音频控制 蓝牙设备 位置服务
网络
HTTP 请求 WebSocket URL 工具
输入与剪贴板
键盘模拟 鼠标模拟 全局热键 剪贴板 窗口管理
存储
SQLite Keychain UserDefaults
媒体
文字识别 二维码
工具
归档 类型标识 分享 定时器 防休眠 并发/协程