问题描述
use std::thread;
use tokio::task; // 0.3.4
#[tokio::main]
async fn main() {
thread::spawn(|| {
task::spawn(async {
println!("123");
});
})
.join();
}
编译时收到警告:
warning: unused `std::result::Result` that must be used
--> src/main.rs:6:5
|
6 | / thread::spawn(|| {
7 | | task::spawn(async {
8 | | println!("123");
9 | | });
10 | | })
11 | | .join();
| |____________^
|
= note: `#[warn(unused_must_use)]` on by default
= note: this `Result` may be an `Err` variant, which should be handled
执行时出现错误:
thread '<unnamed>' panicked at 'must be called from the context of Tokio runtime configured with either `basic_scheduler` or `threaded_scheduler`', src/main.rs:7:9
推荐答案
关键是您需要获得Tokio Handle
.这是对 运行时
的引用,它允许您从运行时之外生成异步任务.
The key piece is that you need to get a Tokio Handle
. This is a reference to a Runtime
and it allows you to spawn asynchronous tasks from outside of the runtime.
使用 #[tokio :: main]
,获取 Handle
的最简单方法是通过 Handle :: current
之前产生另一个线程,然后为可能想要的每个线程提供句柄启动异步任务:
When using #[tokio::main]
, the simplest way to get a Handle
is via Handle::current
before spawning another thread then give the handle to each thread that might want to start an asynchronous task:
use std::thread;
use tokio::runtime::Handle; // 0.3.4
#[tokio::main]
async fn main() {
let threads: Vec<_> = (0..3)
.map(|thread_id| {
let handle = Handle::current();
thread::spawn(move || {
eprintln!("Thread {} started", thread_id);
for task_id in 0..3 {
handle.spawn(async move {
eprintln!("Thread {} / Task {}", thread_id, task_id);
});
}
eprintln!("Thread {} finished", thread_id);
})
})
.collect();
for t in threads {
t.join().expect("Thread panicked");
}
}
您还可以创建 Mutex< Option< Handle>>
,将其初始化为 None
,然后在 tokio :: main
函数的早期将其设置为 Some
.然后,您可以获取该全局变量,将其解包,并在需要时克隆 Handle
:
You could also create a global, mutable singleton of a Mutex<Option<Handle>>
, initialize it to None
, then set it to Some
early in your tokio::main
function. Then, you can grab that global variable, unwrap it, and clone the Handle
when you need it:
use once_cell::sync::Lazy; // 1.5.2
static HANDLE: Lazy<Mutex<Option<Handle>>> = Lazy::new(Default::default);
*HANDLE.lock().unwrap() = Some(Handle::current());
let handle = HANDLE.lock().unwrap().as_ref().unwrap().clone();
另请参阅:
- 如何将任务添加到在另一个线程上运行的Tokio事件循环中?
- 如何在稳定的Rust中同步返回在异步Future中计算出的值?
- 如何为Tokio中的CPU密集型工作创建专用的线程池?
- 如何创建全局的可变单例?
这篇关于如何从Tokio中的非主线程运行异步任务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!