为什么WebViewControlProcess.CreateWebViewControlAsync()从来没有完成?

问题描述 投票:7回答:2

我试着写一个使用Windows.Web.UI.Interop.WebViewControl一定的防锈代码(这是一个进程外,通用的Windows平台包装特意设计使Win32的应用程序可以使用EdgeHTML),这一切都编译,但不会在运行时正常工作。

相关的代码归结到这一点,使用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值,它抱怨)。然而,在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失败。

我错过了某种初始化使用Windows.Web.UI.Interop?或者是有,为什么它不工作的一些其他原因?

winapi rust windows-runtime interop
2个回答
4
投票

原来,问题是线程相关的:在winit箱子是做事件循环在不同的线程,我并没有意识到这一点;我曾错误地认为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实现有一个前几天登陆;当我迁移我的代码使用事件循环,分支2.0的winit,并使用Completed处理不是blocking_get(),这一切都开始工作。

我要澄清有关WinRT的板条箱的blocking_get()调用,它通常会同时原型明显的解决方案:你不能在这种情况下使用它,因为它会导致死锁,因为它会阻止,直到IAsyncOperation完成,但IAsyncOperation将无法完成,直到你处理在事件循环(DispatchMessageW),因为你阻塞线程,这将永远不会发生的消息。


0
投票

尝试初始化WebViewProcessControlwinrt::init_apartment();,它可能需要一个单线程单元(根据本answer)。

Microsoft Edge Developer Guide更多的关注:

最后,电力用户可能会注意到的桌面应用程序的Web浏览器(以前称为Win32WebViewHost),相当于在Win32的WebView,在以下场所内部系统应用程序的外观:

●在Windows 10行动中心。这些通知的源应被理解为从一个Win32应用程序托管的网页视图。

●在设备访问设置UI(设置 - >与隐私>相机/地点/麦克风)。禁用任何这些设置拒绝从Win32中的应用程序托管的所有网页视图访问。

© www.soinside.com 2019 - 2024. All rights reserved.