Tokio的Handle::block_on与Runtime::block_on有何不同?

3
tokio::runtime::Handle.block_ontokio::runtime::Runtime.block_on有什么区别?使用Handle.block_on会导致某些代码挂起,而使用Runtime.block_on则可以正常工作。
以下是我创建Handle的方式,而Runtime与此相同,只是最后两行不同。
let runtime = runtime::Builder::new_multi_thread()
    .enable_all()
    .build()
    .unwrap()
    .handle() // not needed for Runtime
    .clone(); // ---

然后我调用一个函数,该函数如下:

async fn run(){
    // calls get data
}

self.runtime.block_on(run())

这是代码卡住的部分。如果直接在运行时中运行它则正常工作,但使用“Handle”时,程序会卡在“TcpStream::connect()”处。
async fn get_data(addr: String) -> Result<Data> {
    let c = TcpStream::connect(addr.clone()).await?; // hangs here
    let t = get_data_from_connect(c).await?;
    return Ok(t);
}

2
差异在官方文档中有明确解释。您的问题是由于使用函数管道导致丢失了runtime,从而导致运行时关闭,请尝试此代码并查看差异。 - Ömer Erden
@ÖmerErden,“那个函数管道”是什么? - cactus
1
@c-f 方法调用链。当你克隆句柄时,Rust 视克隆的句柄与运行时之间不存在关系,因此运行时被丢弃,这样你就有了一个已关闭的运行时句柄。这就是没有克隆情况下发生的事情,只是没有编译错误,因为通过克隆句柄你规避了编译错误,而不是修复了它。 - Masklinn
@Masklinn 我已经解决了问题并发布了我的解决方案。我不确定该如何更改问题的标题,但它没有意义,因为我在错误的方向上寻找问题。 - cactus
1个回答

2
我通过确保Runtime对象不会超出作用域并被删除来解决了这个问题。我曾经以为只需要Handle来保持运行时状态,但只有Runtime对象本身才能做到这一点。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接