Chr*_*gan 7 winapi interop rust windows-runtime
我正在尝试编写一些使用的Rust代码Windows.Web.UI.Interop.WebViewControl(这是一个明确设计的通用Windows平台进程外包装器,因此Win32应用程序可以使用EdgeHTML),并且它都在编译,但在运行时无法正常工作.
相关代码归结为此,使用winit,winapi和winrt crates:
use winit::os::windows::WindowExt;
use winit::{EventsLoop, WindowBuilder};
use winapi::winrt::roapi::{RoInitialize, RO_INIT_SINGLETHREADED};
use winapi::shared::winerror::S_OK;
use winrt::{RtDefaultConstructible, RtAsyncOperation};
use winrt::windows::foundation::Rect;
use winrt::windows::web::ui::interop::WebViewControlProcess;
fn main() {
assert!(unsafe { RoInitialize(RO_INIT_SINGLETHREADED) } == S_OK);
let mut events_loop = EventsLoop::new();
let window = WindowBuilder::new()
.build(&events_loop)
.unwrap();
WebViewControlProcess::new()
.create_web_view_control_async(
window.get_hwnd() as usize as i64,
Rect {
X: 0.0,
Y: 0.0,
Width: 800.0,
Height: 600.0,
},
)
.expect("Creation call failed")
.blocking_get()
.expect("Creation async task failed")
.expect("Creation produced None");
}
Run Code Online (Sandbox Code Playgroud)
该WebViewControlProcess实例化的工作,并且CreateWebViewControlAsync功能似乎关心它收到的值host_window_handle(它传递0,或一次性从实际HWND价值,它抱怨).然而,这些IAsyncOperation停留确定为AsyncStatus.Started(0),因此blocking_get()呼叫无限期地挂起.
我觉得它有问题WebViewControlProcess:它ProcessId被卡在0,并且它看起来不会产生任何子进程.该ProcessExited事件不会似乎要被解雇(我重视的东西给它实例化后,有没有为它之前被解雇的机会呢?).Terminate()在这种情况下,人们可能会预期呼叫失败,E_FAIL.
我错过了某种初始化使用方法Windows.Web.UI.Interop吗?还是有其他原因导致它不起作用?
事实证明,问题与线程相关:winit 箱正在不同的线程中执行事件循环,而我没有意识到这一点;我错误地认为 winit 是一个无害的抽象,但事实证明并非如此。
\n\n当我尝试最小化和移植一个已知功能的 C++ 示例时,我发现了这一点,这次手动执行所有 Win32 API 调用而不是使用 winit,以便翻译是正确的。我让它工作,并发现了这一点:
\n\n这IAsyncOperation是在事件循环中,在调用的深处实现的DispatchMessageW。那就是Completion调用处理程序的时候。因此,为了完成该操作,您必须在同一线程上运行事件循环。(另一个线程上的事件循环不执行任何操作。)否则,它将保持在该Started状态。
幸运的是,winit已经转向在同一线程中运行的新事件循环,Windows 实现已于几天前落地;当我将代码迁移到使用 winit 的 eventloop-2.0 分支并使用Completed处理程序而不是 时blocking_get(),一切都开始工作了。
我将澄清 winrt crate\xe2\x80\x99sblocking_get()调用,这通常是原型设计时显而易见的解决方案:您可以\xe2\x80\x99t 在这种情况下使用它,因为它会导致死锁,因为它会阻塞直到完成IAsyncOperation,但是IAsyncOperation直到您在事件循环 ( ) 中处理消息时才会完成,这DispatchMessageW永远不会发生,因为您\xe2\x80\x99 正在阻塞线程。