簡體   English   中英

Rust Tokio“未來無法安全地在線程之間發送”,如何使用 watch::channel 共享 Vec<u8> 數據?</u8>

[英]Rust Tokio "future cannot be sent between threads safely ", How to use watch::channel to share Vec<u8> data?

該項目正在實施 TcpListener 服務。 它監視 pc 事件並向 TCP 客戶端廣播。 根據需求(一個生產者和許多消費者)。 但是代碼引發了“未來不能安全地在線程之間發送”錯誤:

use tokio;
use tokio::{io::AsyncWriteExt, net::TcpStream, sync::watch};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
    
    let (tx, mut rx) = watch::channel::<Vec<u8>>(vec![]);

    let mut stream = TcpStream::connect("127.0.0.1:8080").await?;

    tokio::spawn(async move {
        while rx.changed().await.is_ok() {
            stream.write(&*rx.borrow()).await;
        }
    });

    tx.send(vec![1u8, 2u8])?;

    Ok(())
}

操場

給出:

error: future cannot be sent between threads safely
   --> src/main.rs:9:18
    |
9   |       tokio::spawn(async move {
    |  __________________^
10  | |         while rx.changed().await.is_ok() {
11  | |             stream.write(&*rx.borrow()).await;
12  | |         }
13  | |     });
    | |_____^ future created by async block is not `Send`
    |
    = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `std::sync::RwLockReadGuard<'_, Vec<u8>>`
note: future is not `Send` as this value is used across an await
   --> src/main.rs:11:40
    |
11  |             stream.write(&*rx.borrow()).await;
    |                            ----------- ^^^^^^ await occurs here, with `rx.borrow()` maybe used later
    |                            |
    |                            has type `tokio::sync::watch::Ref<'_, Vec<u8>>` which is not `Send`
note: `rx.borrow()` is later dropped here
   --> src/main.rs:11:46
    |
11  |             stream.write(&*rx.borrow()).await;
    |                                              ^
help: consider moving this into a `let` binding to create a shorter lived borrow
   --> src/main.rs:11:27
    |
11  |             stream.write(&*rx.borrow()).await;
    |                           ^^^^^^^^^^^^
note: required by a bound in `tokio::spawn`
   --> /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.22.0/src/task/spawn.rs:163:21
    |
163 |         T: Future + Send + 'static,
    |                     ^^^^ required by this bound in `tokio::spawn`

當我將Vec<u8>更改為u8 &str str 時,它起作用了。 Vec、String 和其他復雜類型將引發異常。

我在谷歌上搜索,但仍然很困惑。 謝謝你的幫助。

我認為是因為Ref<_,T>本身沒有實現Send並且您需要將此類型轉換為Send 我認為唯一明智的方法是在編寫之前先克隆它。 似乎工作。

此外,您需要使用borrow_and_update將值標記為“已看到”。 這是為了確保您不會重復向stream寫入相同的值。

use tokio;
use tokio::{io::AsyncWriteExt, net::TcpStream, sync::watch};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let (tx, mut rx) = watch::channel::<Vec<u8>>(vec![]);

    let mut stream = TcpStream::connect("127.0.0.1:8080").await?;

    tokio::spawn(async move {
        while rx.changed().await.is_ok() {
            let coba = rx.borrow_and_update().clone();
            stream.write(&coba).await;
        }
    });

    tx.send(vec![1u8, 2u8])?;

    Ok(())
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM