Rust如何将Serenity Client所有权转移给tokio新task解决'static生命周期报错
解决方案
该方案也由评论区用户@user4815162342指出:使用async move块捕获client的所有权,在块内部调用start_autosharded方法即可,代码如下:
let shard_join_handle = tokio::task::spawn(async move { client.start_autosharded().await });
原因说明
之前的写法spawn(client.start_autosharded())会先对client做可变借用,调用方法返回Future,再把这个Future传给spawn,整个过程仅产生对client的借用,不会转移所有权,自然无法满足spawn要求的'static生命周期。
而async move块会将用到的client变量的所有权直接转移到块内部,整个Future持有client的所有权,没有外部借用,自然符合'static要求,和是否用Box或者Arc包装没有关系,本质是所有权是否完成转移的问题。
原问题描述
在Serenity框架中,serenity::client::Client结构体提供start_autosharded(&mut self)方法。用户希望该任务在独立线程运行,因此将其放入tokio::task::spawn()中调用,但spawn()要求借用的Client实例具备'static生命周期,而该实例会在创建它的函数结束时被销毁。
用户已经确认这是最后一次调用该Client实例的方法或修改其字段,需要将Client实例的所有权完全转移给新线程。
原报错信息
直接调用报错
--> src/bot_worker.rs:101:45 | 101 | let shard_join_handle = tokio::task::spawn(client.start_autosharded()); | ^^^^^^-------------------- | | | borrowed value does not live long enough | argument requires that `client` is borrowed for `'static` ... 127 | } | - `client` dropped here while still borrowed For more information about this error, try `rustc --explain E0597`.
使用Box包装后仍报错
error[E0597]: `*client` does not live long enough --> src/bot_worker.rs:101:45 | 101 | let shard_join_handle = tokio::task::spawn(client.start_autosharded()); | ^^^^^^-------------------- | | | borrowed value does not live long enough | argument requires that `*client` is borrowed for `'static` ... 127 | } | - `*client` dropped here while still borrowed
原尝试的其他方案
用户也曾考虑使用Arc并查阅相关文档,但未找到满足'static生命周期要求的方案。
内容的提问来源于stack exchange,提问作者Tony Goat
相关产品推荐
相关产品推荐

