我正在尝试编写一些使用 Windows.Web.UI.Interop.WebViewControl
(这是一种通用Windows平台进程外包装,明确设计为Win32应用程序可以使用EdgeHTML)的Rust代码,并且都可以编译,但在运行时无法正常工作。
相关代码使用winit,winapi和winrt包装箱归结为以下内容:
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");
}
WebViewControlProcess
实例化起作用,并且CreateWebViewControlAsync
函数似乎确实关心它作为host_window_handle
接收的值(将其传递为0,或者从实际HWND
值中减去1,然后提示)。但是IAsyncOperation
始终确定为AsyncStatus.Started
(0),因此blocking_get()
调用无限期挂起。A full, runnable demonstration of the issue (with a bit more instrumentation)。
我感觉到
WebViewControlProcess
有问题:它的ProcessId
停留在0,并且看起来没有产生任何子进程。 ProcessExited
事件似乎没有被触发(实例化后我立即向它附加了一些东西,在此之前是否有机会被触发?)。在这种情况下,调用Terminate()
失败,就像人们所期望的那样。我是否错过了使用
E_FAIL
进行的某种初始化?还是有其他原因导致它不起作用? 最佳答案
原来,问题是与线程有关的:winit crate 在另一个线程中进行事件循环,而我没有意识到这一点。我错误地认为winit是一种无害的抽象,事实证明事实并非如此。
当我尝试最小化和移植一个已知功能的C++示例时,我发现了这一点,这次是手动进行所有Win32 API调用,而不是使用winit,以便翻译正确。我得到它的工作,并发现了这一点:IAsyncOperation
在事件循环中实现,位于DispatchMessageW
调用的深处。那是当Completion
处理程序被调用时。因此,要完成操作,必须在同一线程上运行事件循环。 (另一个线程上的事件循环不执行任何操作。)否则,它保持在Started
状态。
幸运的是,winit is already moving to a new event loop which operates in the same thread,几天前已经实现了Windows实现。当我迁移代码以使用winit的eventloop-2.0分支,并使用Completed
处理程序而不是blocking_get()
时,所有这些都开始工作。
我将澄清有关winrt crate的blocking_get()
调用的信息,该调用通常是原型(prototype)制作时的明显解决方案:在这种情况下,您将无法使用它,因为它会导致死锁,因为它会阻塞直到IAsyncOperation
完成,但是IAsyncOperation
直到您处理后才会完成事件循环中的消息(DispatchMessageW
),因为您正在阻塞线程,所以永远不会发生。
关于winapi - 为什么WebViewControlProcess.CreateWebViewControlAsync()从未完成?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54472925/