Closed xiaguangbo closed 7 months ago
rust asynchronous execution always follows a cooperative model. Meaning they never really run in true parallel fashion if they are bound to one thread. You probably first should read about how it works in general, one thing you can do is reading this
If you want to run fully independent async task that you dont want to handle the way described in the link, you can always just spawn a std::thread and create a separate block_on section for it.
While its strictly not needed you can use different async executors that does the job for you here, but it is essentially the same as calling block_on in a certain place. esp-idf-svc is executor agnostic so you can run executors like edge-executor
, embassy-executor
, smol
, tokio
just fine. But in the end you probably would also come to the same place where you would spawn different new executors on a different threads.
@Vollbrecht
Cargo.toml
add tokio = { version = "*", features = ["rt"] }
tokio...block_on
is ok.
tokio...spawn
is no.
but cargo build
no err
fn main() {
// It is necessary to call this function once. Otherwise some patches to the runtime
// implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
esp_idf_svc::sys::link_patches();
// Bind the log crate to the ESP Logging facilities
esp_idf_svc::log::EspLogger::initialize_default();
log::info!("Hello, world!");
tokio::runtime::Builder::new_current_thread()
.enable_all()
.build().unwrap()
.block_on(async {
log::info!("Hello, world!");
loop {
}
});
tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
.spawn(async {
log::info!("Hello, world!");
let mut timer_service = esp_idf_svc::timer::EspTaskTimerService::new()
.unwrap()
.timer_async()
.unwrap();
loop {
log::info!("Hello, world!");
timer_service
.after(std::time::Duration::from_millis(1000))
.await
.unwrap();
}
});
}
use tokio...spawn
in the std::thread::spawn
is no
std::thread::spawn(|| {
tokio...spawn
loop {
std::thread::sleep(std::time::Duration::from_secs(1));
}
});
At present, only block_on can be used. And you can't use tokio::time::sleep
, say libc::...
err
is ok
fn main() {
// It is necessary to call this function once. Otherwise some patches to the runtime
// implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
esp_idf_svc::sys::link_patches();
// Bind the log crate to the ESP Logging facilities
esp_idf_svc::log::EspLogger::initialize_default();
log::info!("Hello, world!");
// esp_idf_svc::io::vfs::initialize_eventfd(5).unwrap();
use tokio::time::{sleep, Duration};
tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
.block_on(async move {
tokio::spawn(async move {
loop {
log::info!("tokio 2");
sleep(Duration::from_millis(1000)).await;
}
});
loop {
log::info!("tokio 1");
sleep(Duration::from_millis(1000)).await;
}
});
}
[dependencies]
# ...
tokio = { version = "*", features = ["rt", "time"] }
There are multiple tasks like this that contain "loop{}", using "... after(...). await" prevents asynchronous tasks from blocking the scheduler entirely. But using "block_on" will block the current thread, I want to create multiple asynchronous tasks in a thread, such as "tokio::task::spawn" to create an asynchronous task, this way of creating will not block the current thread, "esp-rs" is there anything similar