如何创建用于在客户端WebScoket上发送ping的单个线程

发布于 2025-02-10 13:06:25 字数 647 浏览 0 评论 0原文

我编写了此代码,但是在发送ping时,该程序无能为力。当我在程序中执行其他操作时,我该如何产生另一个线程来完成这项工作?

 pub fn sending_ping(addr: Addr<MicroscopeClient>) -> Result<(), ()> {
    info!("Pings started");

    spawn(async move {
        loop {
            info!("Ping");
            match addr.send(Ping {}).await {
                Ok(_) => {
                    info!("Ping sended")
                }
                Err(e) => {
                    warn!("Ping error");
                    return;
                }
            }
            std::thread::sleep(Duration::from_millis((4000) as u64));
        }
    });
    return Ok(());
}

I wrote this code, but when sending pings, the program cannot do anything else. How can I spawn another thread to do this work while I do something else in my program?

 pub fn sending_ping(addr: Addr<MicroscopeClient>) -> Result<(), ()> {
    info!("Pings started");

    spawn(async move {
        loop {
            info!("Ping");
            match addr.send(Ping {}).await {
                Ok(_) => {
                    info!("Ping sended")
                }
                Err(e) => {
                    warn!("Ping error");
                    return;
                }
            }
            std::thread::sleep(Duration::from_millis((4000) as u64));
        }
    });
    return Ok(());
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小镇女孩 2025-02-17 13:06:25

假设您正在使用Tokio,请致电Tokio :: Spawn并不一定保证任务将在单独的线程上执行(尽管可能是)。

这里的问题是std :: thread :: sleep()完全阻止了任务正在运行的线程,这意味着您的ping会异步运行(不是阻止其他任务),但是当您继续进入当前的睡眠时,线程将执行接下来的4秒。

您可以使用非阻止版本的睡眠版本,例如Tokio https://docs.rs/tokio/latest/tokio/time/time/ftime/fn.sleep.html

因此,您的代码看起来像是


 pub fn sending_ping(addr: Addr<MicroscopeClient>) -> Result<(), ()> {
    info!("Pings started");

    spawn(async move {
        loop {
            info!("Ping");
            match addr.send(Ping {}).await {
                Ok(_) => {
                    info!("Ping sended")
                }
                Err(e) => {
                    warn!("Ping error");
                    return;
                }
            }
            tokio::time::sleep(Duration::from_millis(4000)).await;
        }
    });
    return Ok(());
}

您确实想确保任务在另一个线程上散发出来您必须使用 std :: thread :: Spret :: Spawn 但是,您将不得不设置另一个异步运行时。相反,您可以使用 spawn_blocking 至少保证任务的保证是在期望阻止任务的线程上运行


Assuming you are using tokio, calling tokio::spawn does not necessarily guarantee that the task will be executed on a separate thread (though it may be).

The problem here is that std::thread::sleep() completely blocks the thread that the task is running on, meaning your pings will run asynchronously (not blocking other tasks) but when you move on to the sleep nothing else on the current thread will execute for the next 4 seconds.

You can resolve this by using a non-blocking version of sleep, such as the one provided by tokio https://docs.rs/tokio/latest/tokio/time/fn.sleep.html

Thus your code would look like


 pub fn sending_ping(addr: Addr<MicroscopeClient>) -> Result<(), ()> {
    info!("Pings started");

    spawn(async move {
        loop {
            info!("Ping");
            match addr.send(Ping {}).await {
                Ok(_) => {
                    info!("Ping sended")
                }
                Err(e) => {
                    warn!("Ping error");
                    return;
                }
            }
            tokio::time::sleep(Duration::from_millis(4000)).await;
        }
    });
    return Ok(());
}

If you truly want to ensure that the task spawns on a different thread you would have to use std::thread::spawn but you would then have to set up another async runtime. Instead you could use spawn_blocking which at least guarantees the task is run on a thread where tasks are expected to block


零度° 2025-02-17 13:06:25

我通过以下方式解决了这个特定的问题

fn send_heartbeat(&self, ctx: &mut <Self as Actor>::Context) {
    ctx.run_interval(HEARTBEAT_INTERVAL, |act, ctx| {
        if Instant::now().duration_since(act.hb) > CLIENT_TIMEOUT {
            info!("Websocket Client heartbeat failed, disconnecting!");
            act.server_addr.do_send(Disconnect {
                id: act.user_id.clone(),
            });
            ctx.stop();

            return;
        }
    });
}

,但我仍然不知道如何在单独线程的Websocket中启动一些长过程,因此它不会阻止Websocket,tokio =“ 0.2.0”和actix = “ 0.3.0”。

I solved this particular problem in the following way

fn send_heartbeat(&self, ctx: &mut <Self as Actor>::Context) {
    ctx.run_interval(HEARTBEAT_INTERVAL, |act, ctx| {
        if Instant::now().duration_since(act.hb) > CLIENT_TIMEOUT {
            info!("Websocket Client heartbeat failed, disconnecting!");
            act.server_addr.do_send(Disconnect {
                id: act.user_id.clone(),
            });
            ctx.stop();

            return;
        }
    });
}

But I still don't know how to start some long process in a websocket in a separate thread, so that it does not block the websocket, with tokio="0.2.0" and actix="0.3.0".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文