代码之家  ›  专栏  ›  技术社区  ›  Chris Morgan

为什么WebViewControlProcess.CreateWebViewControlAsync()从未完成?

  •  7
  • Chris Morgan  · 技术社区  · 7 年前

    我正试图编写一些使用 Windows.Web.UI.Interop.WebViewControl

    使用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 blocking_get() 电话无限期挂起。

    A full, runnable demonstration of the issue (with a bit more instrumentation) .

    我觉得 WebViewControlProcess ProcessId ProcessExited 事件不会发生 被激发(我在实例化之后立即将一些东西附加到它上,在此之前是否有机会激发它?)。使命感 Terminate() E_FAIL .

    我是否错过了一些使用的初始化 Windows.Web.UI.Interop ? 或者它不起作用还有其他原因吗?

    2 回复  |  直到 7 年前
        1
  •  4
  •   Chris Morgan    7 年前

    事实证明,这个问题与线程相关: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实现在几天前已经登陆;当我迁移代码以使用winit的eventloop-2.0分支,并使用 Completed 处理程序而不是 blocking_get() ,一切都开始起作用了。

    我将澄清winrt板条箱的问题 调用在原型设计时通常是显而易见的解决方案:在这种情况下,您不能使用它,因为它会导致死锁,因为它会阻塞直到 IAsyncOperation IAsyncOperation 在处理事件循环中的消息之前不会完成( 发送消息 ),这将永远不会发生,因为您正在阻塞线程。

        2
  •  0
  •   Drake Wu    7 年前

    WebViewProcessControl 具有 winrt::init_apartment(); 而且它可能需要一个单线程单元(根据这个 answer

    更多关注 Microsoft Edge Developer Guide :

    最后,超级用户可能会注意到桌面应用程序的应用 Web Viewer(以前名为Win32WebViewHost),一个内部系统应用程序 在以下位置表示Win32 WebView:

    在Windows 10操作中心中。这些通知的来源

    在设备访问设置界面中 (设置->隐私->摄像头/位置/麦克风)。禁用任何 这些设置拒绝从Win32应用程序中托管的所有Web视图进行访问。