Open chris-morgan opened 5 years ago
Short answer: I do not know.
I think that I added the Send
bound to all those callbacks just as a precursory safety measure. It's possible that it's totally unnecessary. I would like to think more about all this async
stuff anyway, because I'd like to see if it can be combined with Rust's new async
/await
feature. I could really need some helping hands there, though :-)
I was thinking a similar thing about whether it could be handled in async/await. I haven’t thought too hard about it yet.
I can’t speak for other uses of it, but I can now speak for the WebViewControl
case: you set the Completed
handler, and it will then be called later from the same thread in a DispatchMessageW
(i.e. you need to get an event loop running).
For my particular case, I believe I need the Send
bound not to be present. (I’ve worked around this so far with an unsafe wrapper, and on reflection may continue to need to do something like that anyway.) I picture the code normally going something like this:
let mut control = None;
let operation = process
.create_web_view_control_async(host_window_handle, rect)
.expect("CreateWebViewControlAsync call failed");
operation.set_completed(&AsyncOperationCompletedHandler::new(|_sender, _args| {
control = operation.get_results().unwrap();
if let Some(ref control) = control {
control.navigate(&Uri::create_uri(&FastHString::from("http://www.example.com")).unwrap()).unwrap();
}
}));
We would really need to know if it's guaranteed that async operations always execute on the thread that created the callback. If it's not guaranteed, the Send
bound is necessary, but we could add some unsafe
way to create handler with a !Send
callback.
By the way, I'm experimenting with async/await in a branch: https://github.com/Boddlnagg/winrt-rust/tree/futures-preview
AsyncOperationCompletedHandler::new::<_F_>
includesSend
in its bounds for_F_
, and I’m not sure why it does, or whether it should in fact.For “I’m not sure why”:
AsyncOperationCompletedHandler
is explicitly marked!Send
and!Sync
, so why would its callback need to beSend
?For “I’m not sure whether it should”: my concrete use case is
WebViewControl
, which requires a single-threaded apartment anyway. Given thatWebViewControl
instantiation is done asynchronously and you can’t useblocking_get()
for reasons I won’t contemplate, theSend
bound on the callback is very debilitating; it actively blocks what seems to me the most likely way you want to use it.I have not investigated in any depth, but my intuition says that IAsyncOperation would always be at least effectively single-threaded.
Have I missed something? Is there a reason why that
Send
bound is there?