根据当前运行环境获取tokio运行时句柄的正确方法

yjs*_*hen 7 rust rust-tokio

根据当前运行环境获取 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(())
}

Run Code Online (Sandbox Code Playgroud)

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

当我handle.block_onRuntime::new().unwrap().handle().block_onin main 替换时,代码运行成功。

我想我的get_runtime_handle功能有问题,表达这个问题的正确方法是什么?完整的可运行代码在这里

此外,当该方法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.
Run Code Online (Sandbox Code Playgroud)

小智 11

问题是新运行时的生命周期,它在 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();
}
Run Code Online (Sandbox Code Playgroud)