如何将任务添加到在另一个线程上运行的 Tokio 事件循环?

2023-12-25

我想 https://stackoverflow.com/questions/54279989/is-there-a-way-to-launch-a-tokiodelay-on-a-new-thread-to-allow-the-main-loop-t/54280186?noredirect=1#comment95826753_54280186与 Rocket 服务器一起启动 Tokio 事件循环,然后稍后将事件添加到该循环。我读有没有办法在新线程上启动 tokio::Delay 以允许主循环继续? https://stackoverflow.com/q/54279989/155423,但我仍然不清楚如何实现我的目标。


As 文件指出 https://docs.rs/tokio/0.2.21/tokio/runtime/struct.Runtime.html#method.handle:

返回的句柄可用于生成在此运行时上运行的任务,并且可以进行克隆以允许移动Handle到其他线程。

下面是一个在一个线程中旋转事件循环并让第二个线程在其上生成任务的示例。

use futures::future; // 0.3.5
use std::{thread, time::Duration};
use tokio::{runtime::Runtime, time}; // 0.2.21

fn main() {
    let (shutdown_tx, shutdown_rx) = tokio::sync::oneshot::channel();
    let (handle_tx, handle_rx) = std::sync::mpsc::channel();

    let tokio_thread = thread::spawn(move || {
        let mut runtime = Runtime::new().expect("Unable to create the runtime");

        eprintln!("Runtime created");

        // Give a handle to the runtime to another thread.
        handle_tx
            .send(runtime.handle().clone())
            .expect("Unable to give runtime handle to another thread");

        // Continue running until notified to shutdown
        runtime.block_on(async {
            shutdown_rx.await.expect("Error on the shutdown channel");
        });

        eprintln!("Runtime finished");
    });

    let another_thread = thread::spawn(move || {
        let handle = handle_rx
            .recv()
            .expect("Could not get a handle to the other thread's runtime");

        eprintln!("Another thread created");

        let task_handles: Vec<_> = (0..10)
            .map(|value| {
                // Run this future in the other thread's runtime
                handle.spawn(async move {
                    eprintln!("Starting task for value {}", value);
                    time::delay_for(Duration::from_secs(2)).await;
                    eprintln!("Finishing task for value {}", value);
                })
            })
            .collect();

        // Finish all pending tasks
        handle.block_on(async move {
            future::join_all(task_handles).await;
        });

        eprintln!("Another thread finished");
    });

    another_thread.join().expect("Another thread panicked");

    shutdown_tx
        .send(())
        .expect("Unable to shutdown runtime thread");

    tokio_thread.join().expect("Tokio thread panicked");
}
Runtime created
Another thread created
Starting task for value 0
Starting task for value 1
Starting task for value 2
Starting task for value 3
Starting task for value 4
Starting task for value 5
Starting task for value 6
Starting task for value 7
Starting task for value 8
Starting task for value 9
Finishing task for value 0
Finishing task for value 5
Finishing task for value 4
Finishing task for value 3
Finishing task for value 9
Finishing task for value 2
Finishing task for value 1
Finishing task for value 7
Finishing task for value 8
Finishing task for value 6
Another thread finished
Runtime finished

The Tokio 0.1 的解决方案可以在这篇文章的修订历史中找到 https://stackoverflow.com/revisions/54612971/1.

也可以看看:

  • 如何从 Tokio 中的非主线程运行异步任务? https://stackoverflow.com/q/61292425/155423
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将任务添加到在另一个线程上运行的 Tokio 事件循环? 的相关文章

随机推荐