chore: Keep spawn task on it owner. (#1456)

This commit is contained in:
Jason Lee 2025-10-29 19:11:49 +08:00 committed by GitHub
parent d34ea6640a
commit 7036415662
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 29 additions and 21 deletions

View file

@ -8,7 +8,8 @@ use fake::Fake;
use gpui::{ use gpui::{
Action, AnyElement, App, AppContext, ClickEvent, Context, Entity, Focusable, Action, AnyElement, App, AppContext, ClickEvent, Context, Entity, Focusable,
InteractiveElement, IntoElement, ParentElement, Render, SharedString, InteractiveElement, IntoElement, ParentElement, Render, SharedString,
StatefulInteractiveElement, Styled, TextAlign, Timer, Window, div, prelude::FluentBuilder as _, StatefulInteractiveElement, Styled, Subscription, Task, TextAlign, Timer, Window, div,
prelude::FluentBuilder as _,
}; };
use gpui_component::{ use gpui_component::{
ActiveTheme as _, Selectable, Sizable as _, Size, StyleSized as _, StyledExt, ActiveTheme as _, Selectable, Sizable as _, Size, StyleSized as _, StyledExt,
@ -181,6 +182,8 @@ struct StockTableDelegate {
eof: bool, eof: bool,
visible_rows: Range<usize>, visible_rows: Range<usize>,
visible_cols: Range<usize>, visible_cols: Range<usize>,
_load_task: Task<()>,
} }
impl StockTableDelegate { impl StockTableDelegate {
@ -260,6 +263,7 @@ impl StockTableDelegate {
eof: false, eof: false,
visible_cols: Range::default(), visible_cols: Range::default(),
visible_rows: Range::default(), visible_rows: Range::default(),
_load_task: Task::ready(()),
} }
} }
@ -551,19 +555,18 @@ impl TableDelegate for StockTableDelegate {
fn load_more(&mut self, _: &mut Window, cx: &mut Context<Table<Self>>) { fn load_more(&mut self, _: &mut Window, cx: &mut Context<Table<Self>>) {
self.loading = true; self.loading = true;
cx.spawn(async move |view, cx| { self._load_task = cx.spawn(async move |view, cx| {
// Simulate network request, delay 1s to load data. // Simulate network request, delay 1s to load data.
Timer::after(Duration::from_secs(1)).await; Timer::after(Duration::from_secs(1)).await;
cx.update(|cx| { _ = cx.update(|cx| {
let _ = view.update(cx, |view, _| { let _ = view.update(cx, |view, _| {
view.delegate_mut().stocks.extend(random_stocks(200)); view.delegate_mut().stocks.extend(random_stocks(200));
view.delegate_mut().loading = false; view.delegate_mut().loading = false;
view.delegate_mut().eof = view.delegate().stocks.len() >= 6000; view.delegate_mut().eof = view.delegate().stocks.len() >= 6000;
}); });
}) });
}) });
.detach();
} }
fn visible_rows_changed( fn visible_rows_changed(
@ -591,6 +594,9 @@ pub struct TableStory {
stripe: bool, stripe: bool,
refresh_data: bool, refresh_data: bool,
size: Size, size: Size,
_subscriptions: Vec<Subscription>,
_load_task: Task<()>,
} }
impl super::Story for TableStory { impl super::Story for TableStory {
@ -635,13 +641,13 @@ impl TableStory {
let delegate = StockTableDelegate::new(5000); let delegate = StockTableDelegate::new(5000);
let table = cx.new(|cx| Table::new(delegate, window, cx)); let table = cx.new(|cx| Table::new(delegate, window, cx));
cx.subscribe_in(&table, window, Self::on_table_event) let _subscriptions = vec![
.detach(); cx.subscribe_in(&table, window, Self::on_table_event),
cx.subscribe_in(&num_stocks_input, window, Self::on_num_stocks_input_change) cx.subscribe_in(&num_stocks_input, window, Self::on_num_stocks_input_change),
.detach(); // Spawn a background to random refresh the list
];
// Spawn a background to random refresh the list let _load_task = cx.spawn(async move |this, cx| {
cx.spawn(async move |this, cx| {
loop { loop {
Timer::after(time::Duration::from_millis(33)).await; Timer::after(time::Duration::from_millis(33)).await;
@ -665,8 +671,7 @@ impl TableStory {
}) })
.ok(); .ok();
} }
}) });
.detach();
Self { Self {
table, table,
@ -674,6 +679,8 @@ impl TableStory {
stripe: false, stripe: false,
refresh_data: false, refresh_data: false,
size: Size::default(), size: Size::default(),
_subscriptions,
_load_task,
} }
} }

View file

@ -1,6 +1,6 @@
use std::time::Duration; use std::time::Duration;
use gpui::{px, Context, Pixels, Timer}; use gpui::{px, Context, Pixels, Task, Timer};
static INTERVAL: Duration = Duration::from_millis(500); static INTERVAL: Duration = Duration::from_millis(500);
static PAUSE_DELAY: Duration = Duration::from_millis(300); static PAUSE_DELAY: Duration = Duration::from_millis(300);
@ -16,6 +16,8 @@ pub(crate) struct BlinkCursor {
visible: bool, visible: bool,
paused: bool, paused: bool,
epoch: usize, epoch: usize,
_task: Task<()>,
} }
impl BlinkCursor { impl BlinkCursor {
@ -24,6 +26,7 @@ impl BlinkCursor {
visible: false, visible: false,
paused: false, paused: false,
epoch: 0, epoch: 0,
_task: Task::ready(()),
} }
} }
@ -53,13 +56,12 @@ impl BlinkCursor {
// Schedule the next blink // Schedule the next blink
let epoch = self.next_epoch(); let epoch = self.next_epoch();
cx.spawn(async move |this, cx| { self._task = cx.spawn(async move |this, cx| {
Timer::after(INTERVAL).await; Timer::after(INTERVAL).await;
if let Some(this) = this.upgrade() { if let Some(this) = this.upgrade() {
this.update(cx, |this, cx| this.blink(epoch, cx)).ok(); this.update(cx, |this, cx| this.blink(epoch, cx)).ok();
} }
}) });
.detach();
} }
pub fn visible(&self) -> bool { pub fn visible(&self) -> bool {
@ -75,7 +77,7 @@ impl BlinkCursor {
// delay 500ms to start the blinking // delay 500ms to start the blinking
let epoch = self.next_epoch(); let epoch = self.next_epoch();
cx.spawn(async move |this, cx| { self._task = cx.spawn(async move |this, cx| {
Timer::after(PAUSE_DELAY).await; Timer::after(PAUSE_DELAY).await;
if let Some(this) = this.upgrade() { if let Some(this) = this.upgrade() {
@ -85,7 +87,6 @@ impl BlinkCursor {
}) })
.ok(); .ok();
} }
}) });
.detach();
} }
} }