【问题标题】:Calling an FnMut callback from another thread从另一个线程调用 FnMut 回调
【发布时间】:2017-07-25 19:06:48
【问题描述】:

我正在为 Rust 编写 Phoenix 客户端库,利用来自 rust-websockets 的异步 websocket 客户端。现在我无法弄清楚如何将回调函数传递到处理 websocket 流量的线程中。我有一个简化的结构:

pub struct Socket {
    endpoint:               String,
    connected:              Arc<AtomicBool>,
    state_change_close:     Option<Box<FnMut(String)>>,
}

这个结构有一个connect 函数,布局如下:

pub fn connect(&mut self) -> Result<(), String> {
    if self.connected.load(Ordering::Relaxed) {
        return Ok(())
    }
    
    // Copy endpoint string, otherwise we get an error on thread::spawn
    let connection_string = self.endpoint.clone();
    let (usr_msg, stdin_ch) = mpsc::channel(0);

    let connection_thread = thread::spawn(move || {
        // tokio core for running event loop
        let mut core = Core::new().unwrap();
        let runner = ClientBuilder::new(&connection_string)
            .unwrap()
            .add_protocol("rust-websocket")
            .async_connect_insecure(&core.handle())
            .and_then(|(duplex, _)| {
                let (sink, stream) = duplex.split();
                stream.filter_map(|message| {
                    println!("Received Message: {:?}", message);
                    match message {
                        OwnedMessage::Close(e) => {
                            // This is the line where I am trying to call the callback
                            if let Some(ref mut func) = self.state_change_close {
                                (func)(e.unwrap().reason);
                            }
                            Some(OwnedMessage::Close(e))
                        },
                        _ => None,
                    }
                })
                .select(stdin_ch.map_err(|_| WebSocketError::NoDataAvailable))
                .forward(sink)
            });
        
        // Start the event loop
        core.run(runner).unwrap();
    });
    self.connected.store(true, Ordering::Relaxed);
    return Ok(())
}

当我尝试编译此代码时,我收到以下错误:

error[E0277]: the trait bound `std::ops::FnMut(std::string::String) + 'static: std::marker::Send` is not satisfied
  --> src\socket.rs:99:29
   |
99 |     let connection_thread = thread::spawn(move || {
   |                             ^^^^^^^^^^^^^ the trait `std::marker::Send` is not implemented for `std::ops::FnMut(std::string::String) + 'static`
   |

我尝试将state_change_close 的类型更改为Mutex&lt;Option&lt;...&gt;&gt; 以避免线程安全问题,但这对解决此问题没有帮助。我正在尝试做的事情可能吗?

【问题讨论】:

    标签: multithreading rust


    【解决方案1】:

    在进行了更多研究后,我意识到我只需将 Option&lt;Box&lt;FnMut(String)&gt;&gt; 修改为 Option&lt;Box&lt;FnMut(String) + Send&gt;&gt; 并将其复制到我的代码周围的任何可能设置回调的地方。了解有关 trait 对象的更多信息!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-11
      • 1970-01-01
      • 1970-01-01
      • 2012-08-13
      • 2015-06-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多