为什么WebViewControlProcess.CreateWebViewControlAsync()永远不会完成?

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吗?还是有其他原因导致它不起作用?

Chr*_*gan 4

事实证明,问题与线程相关:winit 箱正在不同的线程中执行事件循环,而我没有意识到这一点;我错误地认为 winit 是一个无害的抽象,但事实证明并非如此

\n\n

当我尝试最小化和移植一个已知功能的 C++ 示例时,我发现了这一点,这次手动执行所有 Win32 API 调用而不是使用 winit,以便翻译是正确的。我让它工作,并发现了这一点:

\n\n

IAsyncOperation是在事件循环中,在调用的深处实现的DispatchMessageW就是Completion调用处理程序的时候。因此,为了完成该操作,您必须在同一线程上运行事件循环。(另一个线程上的事件循环不执行任何操作。)否则,它将保持在该Started状态。

\n\n

幸运的是,winit已经转向在同一线程中运行的新事件循环,Windows 实现已于几天前落地;当我将代码迁移到使用 winit 的 eventloop-2.0 分支并使用Completed处理程序而不是 时blocking_get(),一切都开始工作了。

\n\n

我将澄清 winrt crate\xe2\x80\x99sblocking_get()调用,这通常是原型设计时显而易见的解决方案:您可以\xe2\x80\x99t 在这种情况下使用它,因为它会导致死锁,因为它会阻塞直到完成IAsyncOperation,但是IAsyncOperation直到您在事件循环 ( ) 中处理消息时才会完成,这DispatchMessageW永远不会发生,因为您\xe2\x80\x99 正在阻塞线程。

\n