spawn has the (simplified) signature: fn spawn(f: impl FnOnce() -> T) -> JoinHandle<T> - so it returns a "handle" you can join on to get the result, though since the thread may have panic-ed you need to also unwrap an additional layer of Result:
let handle = spawn(|| 3);
let result = handle.join();
assert_eq!(result, Ok(3));
let handle = spawn(|| panic!("oops"));
let result = handle.join();
assert_eq!(result, Err(Box::new("oops")));
So you'll probably just want to .expect() the first layer to "re-throw" any thread panic.
passing arguments directly to the thread entry point is not possible, but you can capture the arguments in a closure. note however, if you use thread::spawn(), (non-'static) references are not supported, because the thread runs in parallel with its parent thread, so the borrow checker will not be able to check the lifetime is valid.
two solutions:
clone the String and capture it by value:
// make an owned copy of `command`
let command: String = command.clone();
// spawn the thread using a closure, note the `move` keyword
let handle = thread::spawn(move || launch_app(&command));
//...
or use thread::scope() instead of thread::spawn():
thread::scope(|scope| {
let handle = scope.spawn(|| launch_app(&command));
//...
});
as @simonbuchan said, you need to call .join() on the handle returned by spawn() (it's the same for std::thread::spawn() or scope.spawn()), just keep in mind that join() will wrap the return value with another layer of Result, so in your example, you get Result<Result<String, _>, _>. then you just need to handle the error however you like.
how's this question different from 2? can you be more specific?
the argument is like a local variable to the function, if you need to mutate it, you just declare it mut:
note, when you change the signature from &String to &mut String, the callsite needs to be changed accordingly, but the compiler will tell you if the type mismatched.
Just watch out for the fact that std::thread::scope() will block until the spawned threads all exit, so you can't join after the scope.
edit: not sure what I was thinking, actually, of course you can join after the scope closes. join just waits for the exit so if you await it after the scope exit it will immediately complete. So it works, but it's pretty useless!
thank you for the clone method it is what i needed and also i had no idea about thread::scope thanks also for that. I got the solution to my problem and sorry for my english(not my native lang)