我正在编写一个C#应用程序,该应用程序将加载由外部服务器API生成的技术图表网页。我只是尝试使用WebView2在自定义面板中显示我希望加载的网页(因为原始WebBrowser已弃用,并且Cef存在x64问题)。
但是,以下代码在尝试初始化自定义视图时无法正确执行,并引发com异常:
class ChartView : Panel
{
#nullable enable
private string? chartViewFileAddr { get; set; }
#nullable disable
private WebView2 chartWebView { get; set; }
private async void ensureWeb2Init() => await chartWebView.EnsureCoreWebView2Async(null);
private bool isInit = false;
public ChartView(string? chartViewFileAddr) : base()
{
this.chartViewFileAddr= chartViewFileAddr ?? "";
this.BorderStyle = BorderStyle.Fixed3D;
this.Size = new System.Drawing.Size(300, 500);
this.Location = new Point(0, 320);
this.Name = "ChartWebView";
chartWebView= new WebView2();
chartWebView.Size = this.Size;
chartWebView.Location = new System.Drawing.Point(0, 0);
if (isInit == false)
{
Task.Run(() => this.ensureWeb2Init()).Wait();
isInit = true;
}
chartWebView.CoreWebView2.Navigate("google.com"); //base address for testing
this.Controls.Add(chartWebView);
}
}
当它运行时,调用ensureWeb2Init失败。如果我尝试在没有等待函数的情况下运行任务,它将无法异步运行,如果我添加等待函数,异步任务将抛出以下内容:
系统.运行时.互操作服务.COMException:'线程模式设置后无法更改。(0x80010106(RPC_E_CHANGED_MODE))'
不管什么原因,我不能让WebView2正确初始化。我在这里做错了什么吗?谢谢你的帮助。
2条答案
按热度按时间bxgwgixi1#
**问题:**正如注解和其他答案中提到的,问题是在UI线程之外的线程中调用方法。
请注意,尽管此方法是异步的并返回Task,但仍必须像大多数UI控件的大多数公共功能一样在UI线程上调用它。
如果此CoreWebView2示例已被释放,或者调用线程不是创建此对象的线程(通常是UI线程),则抛出InvalidOperationException。
**解决方案:**您可能需要根据自己的要求考虑以下解决方案之一:
*设置“源”属性,而不是调用EnsureCoreWebView2Async
您可以设置WebView2.Source属性,如果CoreWebView2尚未初始化,该属性将隐式初始化CoreWebView2。这样您就不需要调用
EnsureCoreWebView2Async
。例如:*公开异步Initialize方法,并等待在需要时调用该方法
如果你需要调用EnsureCoreWebView2Async,你可以公开一个async方法来初始化并等待你需要的时候调用它。
为控件定义以下方法:
当你想初始化它的时候,可以这样使用它:
*调用EnsureCoreWebView2Async而不等待,然后在CoreWebView2InitializationCompleted事件的事件处理程序中执行其余初始化
您可以调用EnsureCoreWebView2Async而无需等待,然后只需在CoreWebView2InitializationCompleted事件处理程序中执行初始化即可。
更多信息和参考:
zengzsys2#
此异常意味着代码必须在UI线程(特别是创建控件的UI线程)上运行。这对于UI COM组件很常见。
您发布的代码使用
Task.Run
在线程池线程上执行代码。若要在UI线程上运行它,请删除Task.Run
。