Claude-skill-registry gpui-async
Async operations and background tasks in GPUI. Use when working with async, spawn, background tasks, or concurrent operations. Essential for handling async I/O, long-running computations, and coordinating between foreground UI updates and background work.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/gpui-async" ~/.claude/skills/majiayu000-claude-skill-registry-gpui-async && rm -rf "$T"
manifest:
skills/data/gpui-async/SKILL.mdsource content
Overview
GPUI provides integrated async runtime for foreground UI updates and background computation.
Key Concepts:
- Foreground tasks: UI thread, can update entities (
)cx.spawn - Background tasks: Worker threads, CPU-intensive work (
)cx.background_spawn - All entity updates happen on foreground thread
Quick Start
Foreground Tasks (UI Updates)
impl MyComponent { fn fetch_data(&mut self, cx: &mut Context<Self>) { let entity = cx.entity().downgrade(); cx.spawn(async move |cx| { // Runs on UI thread, can await and update entities let data = fetch_from_api().await; entity.update(cx, |state, cx| { state.data = Some(data); cx.notify(); }).ok(); }).detach(); } }
Background Tasks (Heavy Work)
impl MyComponent { fn process_file(&mut self, cx: &mut Context<Self>) { let entity = cx.entity().downgrade(); cx.background_spawn(async move { // Runs on background thread, CPU-intensive let result = heavy_computation().await; result }) .then(cx.spawn(move |result, cx| { // Back to foreground to update UI entity.update(cx, |state, cx| { state.result = result; cx.notify(); }).ok(); })) .detach(); } }
Task Management
struct MyView { _task: Task<()>, // Prefix with _ if stored but not accessed } impl MyView { fn new(cx: &mut Context<Self>) -> Self { let entity = cx.entity().downgrade(); let _task = cx.spawn(async move |cx| { // Task automatically cancelled when dropped loop { tokio::time::sleep(Duration::from_secs(1)).await; entity.update(cx, |state, cx| { state.tick(); cx.notify(); }).ok(); } }); Self { _task } } }
Core Patterns
1. Async Data Fetching
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. Background Computation + UI Update
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. Periodic Tasks
cx.spawn(async move |cx| { loop { tokio::time::sleep(Duration::from_secs(5)).await; // Update every 5 seconds } }).detach();
4. Task Cancellation
Tasks are automatically cancelled when dropped. Store in struct to keep alive.
Common Pitfalls
❌ Don't: Update entities from background tasks
// ❌ Wrong: Can't update entities from background thread cx.background_spawn(async move { entity.update(cx, |state, cx| { // Compile error! state.data = data; }); });
✅ Do: Use foreground task or chain
// ✅ Correct: Chain with foreground task cx.background_spawn(async move { data }) .then(cx.spawn(move |data, cx| { entity.update(cx, |state, cx| { state.data = data; cx.notify(); }).ok(); })) .detach();
Reference Documentation
Complete Guides
-
API Reference: See api-reference.md
- Task types, spawning methods, contexts
- Executors, cancellation, error handling
-
Patterns: See patterns.md
- Data fetching, background processing
- Polling, debouncing, parallel tasks
- Pattern selection guide
-
Best Practices: See best-practices.md
- Error handling, cancellation
- Performance optimization, testing
- Common pitfalls and solutions