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);
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
sid34
  • 37
  • 5
  • Please review how to create a [MCVE] 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](https://play.rust-lang.org) or you can reproduce it in a brand new Cargo project. There are [Rust-specific MCVE tips](//stackoverflow.com/tags/rust/info) as well. – Shepmaster Jan 20 '19 at 19:22
  • Your question is confusing. What is *stopping* you from [starting a new thread](https://doc.rust-lang.org/std/thread/index.html)? – Shepmaster Jan 20 '19 at 19:23

1 Answers1

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::<_, ()>(())
    }))
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • @jhpratt that's really quite a substantially different question. I'd encourage you to ask it separately, along with a suitable MCVE. – Shepmaster Feb 04 '19 at 14:49
  • @jhpratt It'll probably have to wait for a few hours, but I'll put something up for it. – Shepmaster Feb 04 '19 at 20:02