I would like to ask for help with another one of these errors.
It seems I have to avoid a reference being borrowed, and I have seen a number of good ideas but I am out of tricks.
Below this is a minimal example with the same structure as the project code, and produces the same error.
I found out that match &sender.send
in the thread has to take a reference, because if sender
is owned, the next iteration of the loop will not have access to it.
And the closure in thread::spawn(move || loop { ... })
has to be move
, otherwise closure may outlive the current function, but it borrows server_sender_arc, which is owned by the current function
.
I asked this on Stackoverflow as well, where I received some comments:
The whole point of
Rc
andArc
is that you can pass around clones of these wrappers by value without having to clone the data underneath. They perform a similar level of indirection that a reference performs. So why are you trying to pass around a reference to anArc
? - turbulencetoo@turbulencetoo I added the surrounding closure
webview_handle.dispatch(move |webview| { ... }
, which complains that theserver_sender_arc
doesn't implementCopy
, which I could only get around by passing it as a reference. โ Gambhiro
For context, the basic steps (in the project) are:
- thread: start a HTTP server which does things
- build a webview window with channels between it and the server
- thread: start a loop to receive messages from the webview and send them to the server
- run the webview window (blocking on main thread until exits)
// main.rs
extern crate web_view;
use web_view::Content;
use std::sync::{Arc, Mutex, mpsc};
use std::thread::{self, sleep};
use std::time::Duration;
use std::error::Error;
fn main() {
// Channel to pass messages from the server to the webview window.
let (_webview_sender, webview_receiver) = mpsc::channel();
// Channel to pass messages from the webview to the server.
let (server_sender, _server_receiver) = mpsc::channel();
// wrap the channel so that it can be sent across threads
let server_sender_arc = Arc::new(Mutex::new(server_sender));
let c = server_sender_arc.clone();
start_webview(webview_receiver, c).unwrap();
}
fn start_webview(webview_receiver: mpsc::Receiver<String>,
server_sender_arc: Arc<Mutex<mpsc::Sender<String>>>)
-> Result<(), Box<Error>>
{
// Build a webview window and keep a handle before running
struct UserData {
webview_receiver: mpsc::Receiver<String>,
};
{
let webview = web_view::builder()
.title("title")
.content(Content::Url("http://localhost:8080/".to_owned()))
.user_data(UserData {
webview_receiver: webview_receiver,
})
.invoke_handler(|_webview, _arg| Ok(()))
.build().unwrap();
// https://docs.rs/web-view/0.4.0/web_view/struct.Handle.html
let webview_handle = webview.handle();
// Start the thread to receive messages from the webview window, and pass
// them back to a server process.
thread::spawn(move || loop {
{
let res = webview_handle.dispatch(move |webview| {
/*
[rustc] use of moved value: `server_sender_arc`
value moved into closure here, in previous iteration of loop
note: move occurs because `server_sender_arc` ... does not implement the `Copy` trait
*/
let sender = server_sender_arc.lock().expect("Can't lock server sender.");
let UserData {
webview_receiver,
//server_sender,
} = webview.user_data();
match webview_receiver.try_recv() {
Ok(text) => {
match text.as_ref() {
"FileOpen" => {
match &sender.send("tell me about it...".to_owned()) {
Ok(_) => {},
Err(e) => println!("๐ฅ Can't send on user_data.server_sender: {:?}", e),
};
},
_ => {},
};
}
Err(_) => {},
}
Ok(())
});
match res {
Ok(_) => {},
Err(e) => println!("๐ฅ webview_handle.dispatch() {:?}", e),
}
}
sleep(Duration::from_millis(1000));
});
// This will block until the window is closed.
webview.run()?;
}
Ok(())
}
# Cargo.toml
[dependencies]
web-view = "0.4"