名称: gpui-async 描述: GPUI中的异步操作和后台任务。适用于处理异步、spawn、后台任务或并发操作。对于处理异步I/O、长时间运行的计算以及协调前台UI更新和后台工作至关重要。
概述
GPUI提供集成的异步运行时,用于前台UI更新和后台计算。
关键概念:
- 前台任务: UI线程,可以更新实体(
cx.spawn) - 后台任务: 工作线程,CPU密集型工作(
cx.background_spawn) - 所有实体更新都发生在前台线程
快速开始
前台任务(UI更新)
impl MyComponent {
fn fetch_data(&mut self, cx: &mut Context<Self>) {
let entity = cx.entity().downgrade();
cx.spawn(async move |cx| {
// 在UI线程上运行,可以等待和更新实体
let data = fetch_from_api().await;
entity.update(cx, |state, cx| {
state.data = Some(data);
cx.notify();
}).ok();
}).detach();
}
}
后台任务(繁重工作)
impl MyComponent {
fn process_file(&mut self, cx: &mut Context<Self>) {
let entity = cx.entity().downgrade();
cx.background_spawn(async move {
// 在后台线程上运行,CPU密集型
let result = heavy_computation().await;
result
})
.then(cx.spawn(move |result, cx| {
// 返回前台以更新UI
entity.update(cx, |state, cx| {
state.result = result;
cx.notify();
}).ok();
}))
.detach();
}
}
任务管理
struct MyView {
_task: Task<()>, // 如果存储但不访问,前缀用_
}
impl MyView {
fn new(cx: &mut Context<Self>) -> Self {
let entity = cx.entity().downgrade();
let _task = cx.spawn(async move |cx| {
// 任务在丢弃时自动取消
loop {
tokio::time::sleep(Duration::from_secs(1)).await;
entity.update(cx, |state, cx| {
state.tick();
cx.notify();
}).ok();
}
});
Self { _task }
}
}
核心模式
1. 异步数据获取
cx.spawn(async move |cx| {
let data = fetch_data().await?;
entity.update(cx, |state, cx| {
state.data = Some(data);
cx.notify();
})?;
Ok::<_, anyhow::Error>(())
}).detach();
2. 后台计算 + UI更新
cx.background_spawn(async move {
heavy_work()
})
.then(cx.spawn(move |result, cx| {
entity.update(cx, |state, cx| {
state.result = result;
cx.notify();
}).ok();
}))
.detach();
3. 定期任务
cx.spawn(async move |cx| {
loop {
tokio::time::sleep(Duration::from_secs(5)).await;
// 每5秒更新一次
}
}).detach();
4. 任务取消
任务在丢弃时自动取消。存储在结构中以保持活动。
常见陷阱
❌ 不要:从后台任务更新实体
// ❌ 错误:不能从后台线程更新实体
cx.background_spawn(async move {
entity.update(cx, |state, cx| { // 编译错误!
state.data = data;
});
});
✅ 做:使用前台任务或链式调用
// ✅ 正确:与前台任务链式调用
cx.background_spawn(async move { data })
.then(cx.spawn(move |data, cx| {
entity.update(cx, |state, cx| {
state.data = data;
cx.notify();
}).ok();
}))
.detach();
参考文档
完整指南
-
API参考: 参见 api-reference.md
- 任务类型、spawn方法、上下文
- 执行器、取消、错误处理
-
模式: 参见 patterns.md
- 数据获取、后台处理
- 轮询、防抖、并行任务
- 模式选择指南
-
最佳实践: 参见 best-practices.md
- 错误处理、取消
- 性能优化、测试
- 常见陷阱和解决方案