DEV Community

x1957
x1957

Posted on

stop async-std task

I have a situation:

connect to a websocket & send ping message via rest.(It's ridiculous, but the biggest cryptocurrency exchange Binance's websocket api require this).

fn main() {
    task::block_on(async {
        loop { // loop for handle reconnect
            connect to websocket
            task::spawn(async move {
                loop {
                    // delay 30 minutes
                    // rest put
                }
            }); // send rest ping/pong
            read the push message
            // when websocket disconnect finish this iteration
        }
    });
}

The problem is: when iteration finished, the spawn task will run forever.

We can use async-std channel here to recv the stop message and break the loop.

The new problem: When we delay this task, how to get notice that out loop iteration finished?

futures::select solved this problem.

use async_std::sync::{channel, Receiver};
use async_std::task;
use futures::future::{Fuse, FusedFuture, FutureExt};
use futures::select;
use std::time::Duration;

fn main() {
    task::block_on(async move {
        let mut idx: i32 = 0;
        loop {
            idx = idx + 1;
            let (_s, r) = channel::<i32>(1);
            let h = task::spawn(async move {
                loop {
                    let fut = async {
                        task::sleep(Duration::from_secs(2)).await;
                        println!("{} do something!", idx);
                    }.fuse();
                    let mut fut = Box::pin(fut);
                    let mut stop = Box::pin(r.recv().fuse());
                    select! {
                        _ = fut=> {},
                        _ = stop => break,
                    }
                }
            });

            task::sleep(Duration::from_secs(5)).await;
            println!("{} exit", idx);
        }
    });
}

Top comments (0)