Asynchronous 如何在Tokio中从非主线程运行异步任务? 使用std::thread; 使用tokio::task;//0.3.4 #[tokio::main] 异步fn main(){ 线程::spawn(| |{ 任务::生成(异步){ println!(“123”); }); }) .join(); }

Asynchronous 如何在Tokio中从非主线程运行异步任务? 使用std::thread; 使用tokio::task;//0.3.4 #[tokio::main] 异步fn main(){ 线程::spawn(| |{ 任务::生成(异步){ println!(“123”); }); }) .join(); },asynchronous,rust,rust-tokio,Asynchronous,Rust,Rust Tokio,编译时,我收到一条警告: 警告:未使用的`std::result::result`必须使用 -->src/main.rs:6:5 | 6 |/thread::spawn(| |){ 7 | |任务::生成(异步){ 8 | | println!(“123”); 9 | | }); 10 | | }) 11 | | join(); | |____________^ | =注意:`#[警告(未使用的_必须_使用)]`默认打开 =注意:此'Result'可能是'Err'变量,

编译时,我收到一条警告:

警告:未使用的`std::result::result`必须使用
-->src/main.rs:6:5
|
6 |/thread::spawn(| |){
7 | |任务::生成(异步){
8 | | println!(“123”);
9  | |         });
10 | |     })
11 | | join();
| |____________^
|
=注意:`#[警告(未使用的_必须_使用)]`默认打开
=注意:此'Result'可能是'Err'变量,应进行处理
执行时,我得到一个错误:

必须从配置了'basic_scheduler'或'threaded_scheduler'、src/main.rs:7:9的Tokio运行时上下文中调用线程''panicked at'

我有一个作业处理应用程序,它公开一个web API来添加作业并处理作业,但API请求不应等待作业完成(可能需要一段时间)。我使用服务器发送的事件来广播作业结果。这意味着主API服务器正在使用
#[tokio::main]
main
内部执行,但我应该在哪里运行作业执行器?在job executor中,我会有很多等待:比如下载。它们将干扰web API服务器。关键的问题是,我怎样才能同时开始执行这两项死刑

在这个场景中,您需要创建一个单独的线程,在其中您将创建一个Tokio执行器。您得到的错误是,在第二个线程中,没有Tokio执行器(运行时)。您需要手动创建一个,并告诉它运行您的任务。更简单的方法是使用API:

使用东京::运行时::运行时;//0.2.23
//创建运行时
让rt=Runtime::new().unwrap();
//在运行时生成未来
rt.spawn(异步{
println!(“正在工作线程上运行”);
});
在主线程中,已经可以使用
#[tokio::main]
使用执行器。在添加此属性之前,运行时是手动创建的

如果您想坚持异步/等待原则,可以使用:

使用东京;//0.2.23
#[tokio::main]
异步fn main(){
让(u,u)=东京::加入!(启动服务器侦听器(),启动作业处理器());
}

这就是为什么大多数答案都质疑你的方法。虽然非常罕见,但我相信在某些情况下,您希望异步运行时位于另一个线程上,同时还可以手动配置运行时。

关键是您需要一个Tokio。这是对的引用,它允许您从运行时外部生成异步任务

使用时,获取
句柄的最简单方法是在生成另一个线程之前通过,然后将句柄赋予可能要启动异步任务的每个线程:

使用std::thread;
使用tokio::runtime::Handle;//0.3.4
#[tokio::main]
异步fn main(){
let线程:Vec=(0..3)
.map(线程id){
让handle=handle::current();
线程::生成(移动| |{
eprintln!(“线程{}已启动”,线程id);
对于0..3中的任务\u id{
handle.spawn(异步移动{
eprintln!(“线程{}/任务{}”,线程id,任务id);
});
}
eprintln!(“线程{}完成”,线程id);
})
})
.收集();
对于线程中的t{
t、 join().expect(“线程恐慌”);
}
}
您还可以创建一个
Mutex的
,将其初始化为
None
,然后在
tokio::main
函数的早期将其设置为
Some
。然后,您可以获取该全局变量,展开它,并在需要时克隆
句柄

use once_cell::sync::Lazy;//1.5.2
静态句柄:Lazy=Lazy::new(默认值::默认值);
*HANDLE.lock().unwrap()=Some(HANDLE::current());
let handle=handle.lock().unwrap().as_ref().unwrap().clone();
另见:


您在这里的实际目标是什么?为什么要在不同的线程上生成该任务?我认为答案真的取决于你想做什么。@Frxstrem我需要从一个非主线程(t)开始另一个线程,线程(t)应该继续。在此之前,我使用了一个线程池。类似于现在,我决定用async/Wait tokio替换这个池。真正的问题是:为什么要混合线程和任务?如果你使用tokio,最好在任何地方都使用它。任务不是线程,不能从任何地方生成,只能从tokio管理的线程生成。您可能可以使用tokio通道在两者之间进行通信,但这是一项大量的额外工作,并且是一种非常不同的代码结构。您需要获得运行时的句柄,可以将其传递给线程。您可能必须手动创建运行时才能执行此操作。然后,句柄将处理从调用它的线程到tokio worker线程的任务编组。