I want to use Delay
to do some work later. If I use tokio::run
, it just works fine, but it panics when using tokio::spawn
:
use std::sync::mpsc;
use std::time::*;
use tokio::prelude::*; // 0.1.14
fn main() {
let (tx, rx) = mpsc::channel();
let task = tokio::timer::Delay::new(Instant::now() + Duration::from_secs(1))
.map(move |_| {
tx.send(String::from("hello")).unwrap();
()
})
.map_err(|e| {
panic!("{:?}", e);
});
tokio::spawn(task);
let msg = rx.recv().unwrap();
println!("{}", msg);
}
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: SpawnError { is_shutdown: true }', src/libcore/result.rs:1009:5
I need to use spawn
not run
if I want various tasks to work concurrently. How to change the code to make it work?
The documentation for tokio::spawn
states:
This function will panic if the default executor is not set or if spawning onto the default executor returns an error.
Effectively, this means that tokio::spawn
should only be called from inside a call to tokio::run
.
Since you have only a single future to execute, you might as well just pass it directly to tokio::run
. If you had multiple futures, then you can make make use of future::lazy
to construct a lazily-evaluated future that will call spawn
when it eventually runs:
use std::time::*;
use tokio::prelude::*; // 0.1.14
fn main() {
tokio::run(futures::lazy(|| {
tokio::spawn(wait_one_sec().map(|_| println!("One")));
tokio::spawn(wait_one_sec().map(|_| println!("Two")));
Ok(())
}));
}
fn wait_one_sec() -> impl Future<Item = (), Error = ()> {
tokio::timer::Delay::new(Instant::now() + Duration::from_secs(1))
.map(drop)
.map_err(|e| panic!("{:?}", e))
}
Note that if you forget the futures::lazy
then you will get the same error. This is because the arguments to functions are evaluated eagerly, which means that the call to tokio::spawn
happens first, causing the same sequence of events.
use std::sync::mpsc;
I think it's highly doubtful that you want to use the standard libraries channels, as they are not async-aware and thus will block — a very bad thing in async code.
Instead, you probably want futures::sync::mpsc
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With