1

I am trying to read input lines from the console. I am using the async_std crate for reading the lines.

The stdin.readline is called at multiple places.

Is there a way to cancel or flush the previous instance of stdin.read_line, before calling trying to read stdin.read_line again?

rust code:

let create_spawn = async move {
    let stdin = io::stdin();
    let mut input_line = String::new();
    
    let r = stdin.read_line(&mut input_line);
    let l = r.await?;
    
    log::debug!("received the input line: {}", input_line);
    Ok::<(), anyhow::Error>(())
};
    let c1 = tokio::spawn(create_spawn);

    delay();

    // <---cancel the previous instance of `stdin.read_line` --->
    let c2 = tokio::spawn(create_spawn);
Ganesh Rathinavel
  • 1,243
  • 4
  • 17
  • 38
  • Just read lines in a loop until `.read_line` returns `Ok(0)` which indicates no errors with 0 bytes read (which is equivalent to reaching the end of the stream). – Alexey S. Larionov Aug 07 '21 at 14:57
  • Are you using `tokio` and `async_std`? They are both different async runtimes. – harmic Aug 08 '21 at 03:24

1 Answers1

0

You mention that you are using async_std, but your sample is also using tokio.

Simplifying your program to use async-std throughout, and applying a little artistic licence:

use async_std::{io, task};
use std::{thread::sleep, time::Duration};

async fn read_from_stdin() -> io::Result<()> {

    let stdin = io::stdin();
    let mut input_line = String::new();

    println!("Waiting for input");
    let r = stdin.read_line(&mut input_line);
    let n = r.await?;
    
    println!("received the input line ({} bytes): {}", n, input_line);
    Ok(())
}

fn main() {

    let c1 = task::spawn(read_from_stdin());

    sleep(Duration::from_secs(10));

    task::block_on(c1.cancel());

    println!("Cancelled Input!\n");

    let c2 = task::spawn(read_from_stdin());
    
    sleep(Duration::from_secs(10));

}

You can't spawn the same future twice, so I moved your create_spawn into an async function called read_from_stdin. Each time that function is called it will return a future which completes when a line is read from stdin.

Calls to task::spawn return a JoinHandle, which exposes a cancel method which allows you to cancel the task that you have spawned. You can then spawn a new task to read from stdin.

harmic
  • 28,606
  • 5
  • 67
  • 91
  • I tried to make the changes in my code as suggested here. But unfortunately the app isnt releasing the `stdin.read_line` of `c1`. I have to input a line before I can read the line for `c2`. The same issue i was facing yesterday. Thanks for your suggestions though! – Ganesh Rathinavel Aug 08 '21 at 14:14