Is there a way to launch a tokio::Delay on a new thread to allow the main loop to continue?
Asked Answered
S

1

1

I am trying to run a function at the end of a delay if the timer is not canceled. The use case is a press and hold / double tap for user input.

The main issue that I am having is that the tokio::run(task); stops the main loop from executing thus prevents me from evaluating the state of the users control.

fn start_timer(&self) {
    let function_name = self.combo.function_name.clone();
    let when = Instant::now() + Duration::from_millis(self.combo.timer_value as u64);
    let task = Delay::new(when)
        .and_then(move |_| {
            call_function(&function_name, InteropParams::Button);
            Ok(())
        })
        .map_err(|e| panic!("delay errored; err={:?}", e));

    tokio::run(task);
}
Sienese answered 20/1, 2019 at 19:10 Comment(2)
Please review how to create a minimal reproducible example and then edit your question to include it. We cannot tell what crates, types, traits, fields, etc. are present in the code. Try to produce something that reproduces your error on the Rust Playground or you can reproduce it in a brand new Cargo project. There are Rust-specific MCVE tips as well.Sennet
Your question is confusing. What is stopping you from starting a new thread?Sennet
S
5

Yes, you can start a new OS level thread and run a Tokio event loop there:

use futures::future::Future; // 0.1.25
use std::{
    thread,
    time::{Duration, Instant},
};
use tokio::timer::Delay; // 0.1.14 

fn main() {
    let t = thread::spawn(|| {
        let when = Instant::now() + Duration::from_millis(100);
        let task = Delay::new(when)
            .and_then(move |_| {
                println!("Delay expired");
                Ok(())
            })
            .map_err(|e| panic!("delay errored: {}", e));

        tokio::run(task);
    });

    t.join().unwrap();
}

You can also use Tokio's tasks via tokio::spawn:

use futures::future::{self, Future}; // 0.1.25
use std::time::{Duration, Instant};
use tokio::timer::Delay; // 0.1.14

fn main() {
    tokio::run(future::lazy(|| {
        tokio::spawn({
            let when = Instant::now() + Duration::from_millis(100);
            Delay::new(when)
                .and_then(move |_| {
                    println!("Delay 100 expired");
                    Ok(())
                })
                .map_err(|e| panic!("delay errored: {}", e))
        });

        tokio::spawn({
            let when = Instant::now() + Duration::from_millis(200);
            Delay::new(when)
                .and_then(move |_| {
                    println!("Delay 200 expired");
                    Ok(())
                })
                .map_err(|e| panic!("delay errored: {}", e))
        });

        future::ok::<_, ()>(())
    }))
}
Sennet answered 20/1, 2019 at 19:33 Comment(2)
@jhpratt that's really quite a substantially different question. I'd encourage you to ask it separately, along with a suitable MCVE.Sennet
@jhpratt It'll probably have to wait for a few hours, but I'll put something up for it.Sennet

© 2022 - 2024 — McMap. All rights reserved.