【问题标题】:The proper method to get tokio runtime handle based on current running environment根据当前运行环境获取tokio运行时句柄的正确方法
【发布时间】:2021-08-19 00:14:50
【问题描述】:

根据当前运行环境获取 tokio 运行时句柄的惯用方式是什么?

  • 对于已经在 tokio 运行时运行的方法,我想使用Handle.try_current().unwrap() 来获取当前的。
  • 对于未在 tokio 中运行的方法,我可以创建一个新方法:Runtime::new().unwrap().handle()

但是,当我将代码编写为:

fn get_runtime_handle() -> Handle {
    match Handle::try_current() {
        Ok(h) => h,
        Err(_) => Runtime::new().unwrap().handle().clone(),
    }
}

async fn a_async() -> Result<()> {
    ....
}

fn a() -> Result<()> {
   let handle = get_runtime_handle();
   handle.block_one (async { a_async().await; })
}

fn main() -> Result<()> {
    a();

    Ok(())
}

并在里面调用tokio::fs::read_dir,代码崩溃Error: Custom { kind: Other, error: "background task failed" }

当我在 main 中将 handle.block_on 替换为 Runtime::new().unwrap().handle().block_on 时,代码运行成功。

我想我的get_runtime_handle 函数有问题,正确的表达方式是什么? 完整的可运行代码是here

此外,当 get_runtime_handle 方法在 tokio 运行时内运行时,项目中的其他单元测试会抱怨:

thread 'main' panicked at 'Cannot start a runtime from within a runtime. 
This happens because a function (like `block_on`) attempted to block the
current thread while the thread is being used to drive asynchronous tasks.

【问题讨论】:

    标签: rust rust-tokio


    【解决方案1】:

    问题在于新运行时的生命周期,它在 get_runtime_handle() 结束时被删除。如果函数创建一个,您应该返回运行时。

    use tokio::runtime::{Runtime, Handle};
    
    fn get_runtime_handle() -> (Handle, Option<Runtime>) {
        match Handle::try_current() {
            Ok(h) => (h, None),
            Err(_) => {
                  let rt = Runtime::new().unwrap();
                  (rt.handle().clone(), Some(rt))
                }
        }
    
    
    fn main() {
        // let _ = Runtime::new().unwrap();
        let (handle, rt) = get_runtime_handle();
    }
    

    【讨论】:

    • 嗨,谢谢你的回答,但第二个问题仍然存在:因为我使用 a_async() 使用 block_on 来实现 fn a(),当 a()tokio::main 中被调用时,@ 987654326@block_on`) 试图阻止......节目。我该如何处理?
    • 这是因为当您使用 tokio::main 时,主函数位于运行时内,并且就像错误所说的您无法在运行时内运行运行时一样。 block_on 是运行时的入口点,我很确定 tokio::main 使用它来运行 async main。在这种情况下您要使用的是spawnspawn_blocking
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-08
    • 1970-01-01
    • 2018-11-03
    • 2013-04-13
    • 1970-01-01
    • 2019-11-12
    • 1970-01-01
    相关资源
    最近更新 更多