Joylei / eip-rs

rseip - EIP&CIP client in pure Rust, for generic CIP and AB PLC
MIT License
47 stars 6 forks source link

Future cannot be sent between threads safely #8

Closed aruddy-slb closed 2 years ago

aruddy-slb commented 2 years ago

I have worked through the example you provided in the ReadMe, and it works great! I can read/write tags without a hitch.

The issue arises when I attempt to create a background task to handle the reading/writing of tags. Rust Analyzer gives me the following error:

future cannot be sent between threads safely
the trait `std::marker::Send` is not implemented for `dyn std::future::Future<Output = Result<rseip::client::ab_eip::TagValue<i32>, ClientError>>`rustc
[main.rs(18, 32): ]()future is not `Send` as it awaits another future which is not `Send`
[spawn.rs(127, 21): ]()required by a bound in `tokio::spawn` 

However, in the docs, it specifically says that ClientError is Send and TagValue is Send so long as T is also Send. This might just be my inexperience with tokio, but I am wondering if you could shed some light on how to do this properly.

Here is my sample code:

use rseip::client::ab_eip::*;
use rseip::precludes::*;

#[tokio::main]
async fn main(){
    tokio::spawn(async move {
        background().await;
    });
}

async fn background() -> Result<()> {
    let mut client = AbEipClient::new_host_lookup("192.168.0.83")
        .await?
        .with_connection_path(PortSegment::default());
    let tag = EPath::parse_tag("test_car1_x")?;
    println!("read tag...");
    let value: TagValue<i32> = client.read_tag(tag.clone()).await?;
    println!("tag value: {:?}", value);
    client.write_tag(tag, value).await?;
    println!("write tag - done");
    client.close().await?;
    Ok(())
}

Thank you in advance!

simonkampe commented 2 years ago

Can this be worked around using the anyhow crate like so?

fn read_tag() -> anyhow::Result<i32> {
    let tag = EPath::parse_tag("my tag name")?;
    let value: TagValue<i32> = client
        .read_tag(tag.clone())
        .await
        .context("Failed to read tag!")?;
    Ok(value.value)
}

But I agree it would be nice if it was fixed :)

simonkampe commented 2 years ago

It ain't pretty, but I fixed the issue (I think? It compiles anyways) here: https://github.com/simonkampe/eip-rs

Joylei commented 2 years ago

let me try