下面是这个问题的后续报道。
我正在将一个WPF应用程序从CEFSharp移植到WebView2。我有一个需要从HostObject窗口的js访问的WebView2。就这样,脱光衣服。
using System;
using System.Runtime.InteropServices;
namespace webview2Demo
{
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
public class Api
{
public string Username { get; set; }
public string Version = "1.1.1";
public Api() //ctor
{
}
}
}
我可以在WebView2控件的NavigationStarting事件中成功地使用这一行使对象从Javascript中可见。到目前一切尚好。
webView.CoreWebView2.AddHostObjectToScript("api", new API());
我可以取回这样的公共财产和成员。到目前一切尚好。
(async function foo () {
const api = chrome.webview.hostObjects.api
const ver = await api.Version
alert (ver)
})();
我的问题是:在没有任何异步竞争条件或死锁风险的情况下,能够可靠地设置这样的属性吗?api.Username = 'whoever'
似乎可以工作,但我还没有找到文档。
(async function foo () {
const api = chrome.webview.hostObjects.api
api.Username = 'whoever'
const user = await api.Username
alert (user)
})();
文档称,HostObject是通过承诺公开的。,我打得对吗?
发布于 2021-08-04 22:49:18
当您在JavaScript代理上为通过CoreWebView2.AddHostObjectToScript创建的主机对象设置属性时,与获取属性或调用方法不同,分配返回的值与已分配的值相同,而不是表示该赋值完成的承诺。属性赋值确实会生成一条发送回WebView2主机应用程序进程的消息,该属性将被分配,您将无法保证它何时完成。
setHostProperty
或者,您也可以使用setHostProperty,这是一种方法,它将执行属性分配并返回在完成属性分配时将解析的承诺。
(async function foo () {
const api = chrome.webview.hostObjects.api
await api.setHostProperty('Username', 'whoever');
const user = await api.Username
alert (user)
})();
同步代理
还有代理的同步版本。在任何地方,异步代理都返回承诺--同步代理,而不是阻止JavaScript线程等待来自WebView2主机进程的响应。通常,您不希望阻止等待跨进程调用的JavaScript线程,但在某些情况下,它可能更实用或更可接受。异步代理有一个sync
方法,它将返回代理的同步版本(异步)。
(async function foo () {
// Note the one await call to get from async proxies to sync proxies
const syncHostObjects = await chrome.webview.hostObjects.sync;
const api = syncHostObjects.api;
api.Username = 'whoever';
const user = api.Username
alert (user)
})();
依赖队列
由于所有JavaScript代理消息都运行在同一个队列上,并且必须在WebView2主机应用程序进程中的同一个线程上处理,所以可能使用属性设置程序而不是等待其完成,然后调用getter,仍然会迫使get消息等待设置完成,并且您的原始代码没有问题。
https://stackoverflow.com/questions/68623267
复制相似问题