新しい tokio スレッド内で async-function を呼び出そうとすると、一部の関数でエラーが発生します。
この最小限の例では、クレート tokio と iota-streams が使用されています。メソッド send_announce() は非同期で、アドレスを返します。このメソッドを待機すると、std::Marker::Send 特性が実装されていないことを示すコンパイル エラーが発生します。
dyn std::future::Future<Output = Result<GenericMessage<TangleAddress, BinaryBody>, iota_streams::iota_streams_core::Error>>
dyn std::future::Future<Output = Result<(), iota_streams::iota_streams_core::Error>>
dyn std::future::Future<Output = Result<&mut iota_streams::iota_streams_ddml::command::sizeof::Context<KeccakF1600>, iota_streams::iota_streams_core::Error>>
dyn std::future::Future<Output = Result<&mut iota_streams::iota_streams_ddml::command::wrap::Context<KeccakF1600, &mut [u8]>, iota_streams::iota_streams_core::Error>>
私の理解では、問題は 1 つ以上の Sync/Send トレイトの実装の欠如であり、スレッド間でデータを渡すことができるようにするために、Rust はチェーン全体に Sync と Send を実装する必要があります。
ドキュメントには、言及された構造体には自動特性として Sync と Send が実装されていると記載されています: (iota_streams_core::Error、wrap::Context、TangleAddress、BinaryBody、command::sizeof::Context、KeccakF1600 ...)
メイン スレッド内で同じ関数を呼び出すと、正常に動作します。
send_announce() から得られた未来を Box にラップし、Send トレイト unsafe を実装し、応答を struct にラップしようとしましたが、コンパイル エラーを変更することはありませんでした。
この文脈では、動的な将来の反応は何らかの問題があるようです。私はさびに慣れていないので、この問題を解決する方法について私が得ることができるあらゆる助けやアイデアをいただければ幸いです。このアプローチは可能ですか?
私のプログラムは呼び出しによって呼び出され、別のスレッドで要求を処理する必要があります。このスレッド内には、たとえばこのお知らせリンクが生成されます。
示されている例は、問題を重要な部分に絞り込むための最小限の例です。Ubuntu で錆安定とナイトリーでテスト済み。
// main.rs
use iota_streams::{
app::transport::tangle::client::Client,
app_channels::api::tangle::{Author, ChannelType},
core::Result,
};
use rand::Rng;
#[tokio::main]
async fn main() -> Result<()> {
//
// This works fine
//
let seed = generate_seed();
let client = Client::new_from_url("https://chrysalis-nodes.iota.org");
let mut author = Author::new(&seed, ChannelType::SingleBranch, client.clone());
//
// No error occurs here
//
let announcement_link = author.send_announce().await?;
//
// Spawn new thread
//
tokio::spawn(async move {
let seed = generate_seed();
let client = Client::new_from_url("https://chrysalis-nodes.iota.org");
//
// Error occurs here
//
let announcement_link = author.send_announce().await?;
Ok(())
});
Ok(())
}
// Make a seed
const ALPH9: &str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ9";
fn generate_seed() -> String {
let seed: String = (0..81)
.map(|_| { ALPH9
.chars().nth(rand::thread_rng().gen_range(0..27)).unwrap()
}).collect::<String>();
seed
}
# Cargo.toml
[package]
name = "example"
version = "0.1.0"
edition = "2021"
[dependencies]
iota-streams = { git = "https://github.com/iotaledger/streams", branch = "develop"}
tokio = { version = "1.17.0", features = ["full"] }
rand = "0.8.5"
error: generator cannot be sent between threads safely
--> src/main.rs:17:5
|
17 | tokio::spawn(async {
| ^^^^^^^^^^^^ future created by async block is not `Send`
|
= help: the trait `std::marker::Send` is not implemented for `dyn std::future::Future<Output = Result<GenericMessage<TangleAddress, BinaryBody>, iota_streams::iota_streams_core::Error>>`
note: required by a bound in `tokio::spawn`
--> /home/-/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.17.0/src/task/spawn.rs:127:21
|
127 | T: Future + Send + 'static,
| ^^^^ required by this bound in `tokio::spawn`
error: generator cannot be sent between threads safely
--> src/main.rs:17:5
|
17 | tokio::spawn(async {
| ^^^^^^^^^^^^ future created by async block is not `Send`
|
= help: the trait `std::marker::Send` is not implemented for `dyn std::future::Future<Output = Result<(), iota_streams::iota_streams_core::Error>>`
note: required by a bound in `tokio::spawn`
--> /home/-/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.17.0/src/task/spawn.rs:127:21
|
127 | T: Future + Send + 'static,
| ^^^^ required by this bound in `tokio::spawn`
error: generator cannot be sent between threads safely
--> src/main.rs:17:5
|
17 | tokio::spawn(async {
| ^^^^^^^^^^^^ future created by async block is not `Send`
|
= help: the trait `std::marker::Send` is not implemented for `dyn std::future::Future<Output = Result<&mut iota_streams::iota_streams_ddml::command::sizeof::Context<KeccakF1600>, iota_streams::iota_streams_core::Error>>`
note: required by a bound in `tokio::spawn`
--> /home/-/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.17.0/src/task/spawn.rs:127:21
|
127 | T: Future + Send + 'static,
| ^^^^ required by this bound in `tokio::spawn`
error: generator cannot be sent between threads safely
--> src/main.rs:17:5
|
17 | tokio::spawn(async {
| ^^^^^^^^^^^^ future created by async block is not `Send`
|
= help: the trait `std::marker::Send` is not implemented for `dyn std::future::Future<Output = Result<&mut iota_streams::iota_streams_ddml::command::wrap::Context<KeccakF1600, &mut [u8]>, iota_streams::iota_streams_core::Error>>`
note: required by a bound in `tokio::spawn`
--> /home/-/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.17.0/src/task/spawn.rs:127:21
|
127 | T: Future + Send + 'static,
| ^^^^ required by this bound in `tokio::spawn`
error: could not compile `teststh` due to 4 previous errors