You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tokio单线程运行时是否提供run_until_stalled等效功能?

Tokio单线程运行时实现类似run_until_stalled的方案

Tokio单线程运行时本身没有直接对应futures::LocalPool::run_until_stalled的API,但可以通过两种方式手动模拟这个行为:

方式一:用Runtime::block_on结合自定义循环

创建单线程Runtime后,在每帧循环里通过yield_now()触发Tokio调度所有可运行任务,直到没有任务能继续推进。示例代码:

use tokio::runtime::Builder;

fn main() {
    let rt = Builder::new_current_thread().build().unwrap();
    let _enter = rt.enter();

    // 游戏主循环
    loop {
        // 处理游戏输入、渲染等同步逻辑
        process_game_logic();

        // 驱动异步任务直到停滞
        while rt.block_on(tokio::task::yield_now()).is_ready() {
            // 空循环,直到所有可运行任务执行完毕
        }

        // 帧结束处理
        end_frame();
    }
}

fn process_game_logic() { /* 你的同步游戏逻辑 */ }
fn end_frame() { /* 帧收尾逻辑 */ }

核心逻辑是tokio::task::yield_now()会让出线程,让Tokio调度所有可运行任务;当所有任务都进入等待状态(停滞),yield_now()会返回Pending,循环随即退出。

方式二:通过Runtime Handle手动调度任务

如果已经持有Runtime的Handle,可以直接操作内部调度器,轮询所有任务直到停滞:

use futures::future::poll_fn;
use tokio::runtime::Handle;

fn drive_until_stalled(handle: &Handle) {
    handle.block_on(poll_fn(|cx| {
        // 触发一次调度器轮询
        handle.inner().park().poll_once(cx);
        // 检查是否还有可运行任务,没有则返回Pending结束循环
        if handle.inner().has_ready_tasks() {
            std::task::Poll::Ready(())
        } else {
            std::task::Poll::Pending
        }
    }));
}

这个方法直接对接Tokio内部调度逻辑,确保所有可推进的任务都被执行完毕。

注意事项

  • 必须使用单线程Runtime(Builder::new_current_thread()),避免多线程调度的额外复杂度,适配游戏循环单线程驱动的场景。
  • 异步任务里不要执行阻塞操作,否则会卡住整个游戏循环;阻塞逻辑请用tokio::task::spawn_blocking处理。

内容的提问来源于stack exchange,提问作者rozina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 04:05:02