3

.NET,WinForms。

调用是从 UI 线程(按钮 - 单击)触发的。来自 ExecuteScriptAsync 的返回应该继续同步处理,即它们应该再次与调用上下文同步。我在这里失败了。

我试过例如:

private void buttonTest1_Click(object sender, EventArgs e) {
        MessageBox.Show(GetMathResult());
    }

    String GetMathResult() {
        // a) Application freezes
        //var result = webView.ExecuteScriptAsync("Math.sin(Math.PI/2)").GetAwaiter().GetResult();
        //return result;

        // b) return null
        //String result = null;
        //Task task = new Task(async () => { result = await webView.ExecuteScriptAsync("Math.sin(Math.PI/2)"); }); 
        //task.RunSynchronously();
        //return result;

        // c) Excepion: // InvalidCastException: Das COM-Objekt des Typs "System.__ComObject" kann nicht in den Schnittstellentyp "Microsoft.Web.WebView2.Core.Raw.ICoreWebView2Controller" umgewandelt werden. Dieser Vorgang konnte nicht durchgeführt werden, da der QueryInterface-Aufruf an die COM - Komponente für die Schnittstelle mit der IID "{4D00C0D1-9434-4EB6-8078-8697A560334F}" aufgrund des folgenden Fehlers nicht durchgeführt werden konnte: Schnittstelle nicht unterstützt(Ausnahme von HRESULT: 0x80004002(E_NOINTERFACE)).
        //String result = Task.Run(() => GetMathResultTask()).Result;
        //return result;
    }

    Task<String> GetMathResultTask() {
        return webView.ExecuteScriptAsync("Math.sin(Math.PI/2)");
    }

这也不起作用(见错误):

private void buttonTest3_Click(object sender, EventArgs e) {
        MessageBox.Show(Y());
    }

    String Y() {
        String result = null;
        var autoResetEvent = new AutoResetEvent(false);

        Task.Run(async () =>
        {
            try {
                result = await webView.ExecuteScriptAsync("Math.sin(Math.PI/2)");
            }
            catch (Exception exc) {
                // !!! {"Das COM-Objekt des Typs \"System.__ComObject\" kann nicht in den Schnittstellentyp \"Microsoft.Web.WebView2.Core.Raw.ICoreWebView2Controller\" umgewandelt werden. Dieser Vorgang konnte nicht durchgeführt werden, da der QueryInterface-Aufruf an die COM-Komponente für die Schnittstelle mit der IID \"{4D00C0D1-9434-4EB6-8078-8697A560334F}\" aufgrund des folgenden Fehlers nicht durchgeführt werden konnte: Schnittstelle nicht unterstützt (Ausnahme von HRESULT: 0x80004002 (E_NOINTERFACE))."}
                Console.WriteLine(exc.ToString()); 
            }
            finally {
                autoResetEvent.Set();
            }
        });
        autoResetEvent.WaitOne();

        return result;
    }

我正在竞标代码示例。

4

4 回答 4

2

要从ExecuteScriptAsyncuseawait运算符获取结果,如下所示:

private async void Form1_Load(object sender, EventArgs e)
{
    await this.webView21.EnsureCoreWebView2Async();
}
private async void button1_Click(object sender, EventArgs e)
{
    var result = await webView21.ExecuteScriptAsync("Math.sin(Math.PI/2)");
    MessageBox.Show(result);
}

注意:对于那些想要使用的人WebView2,您需要在您的机器上安装WebView2 RuntimeMicrosoft Edge Chromium 。您还需要在项目中安装WebView2 NuGet 包

于 2020-12-16T18:45:29.647 回答
1

我可能不得不那样使用它。这是我能找到的最佳解决方案:

private void buttonTest3_Click(object sender, EventArgs e) {
        GetMathResult_v3((x) => {
            MessageBox.Show(x);
            // .. 
        });
    }

    void GetMathResult_v3(Action<String> callbackAction) {

        var task = webView.ExecuteScriptAsync("Math.sin(Math.PI/2)");

        task.ContinueWith(
            (x) => {
                String mathResult = x.Result;
                callbackAction(mathResult);
            }
            , TaskScheduler.FromCurrentSynchronizationContext()
        );

    }
于 2020-12-17T09:47:31.803 回答
0

对于在 WinForms 下使用 WebView2 并寻找安全、简单和反阻塞解决方案的任何人来说,这些代码行似乎是合乎逻辑的:

public void WaitAsyncTask(int waitSecond, System.Runtime.CompilerServices.TaskAwaiter activeTask)
{
        double secondDiffer = (DateTime.Now - WaitStartTime).TotalSeconds;
        while (secondDiffer < waitSecond)
        {
            secondDiffer = (DateTime.Now - WaitStartTime).TotalSeconds;
            Application.DoEvents();
            if (activeTask.IsCompleted)
                break;
        }
}

WaitStartTime是用户在异步进程开始之前定义和分配的。

要从 main 方法调用此方法:

public async Task ExecJavaScript(string userScript)
{
    MacroJava = "";
    var tr = await ((Microsoft.Web.WebView2.WinForms.WebView2)wbSelectedTech).CoreWebView2.ExecuteScriptAsync(userScript);
    MacroJava = System.Text.Json.JsonSerializer.Deserialize<dynamic>(tr);
    MacroJava = MacroJava is null ? "" : MacroJava.ToString();
}

现在从此方法调用这些辅助方法:

public string GetelementValue(string elmId)
{
   var aw = ExecJavaScript("document.getElementById('" + elmId + "').innerHTML").GetAwaiter();
   TimeWaitStart = DateTime.Now;
   WaitAsyncTask(2, aw);//for 2 seconds maximum 
   return MacroJava.ToString();
}
于 2021-06-17T06:01:28.363 回答
-1
webView.ExecuteScriptAsync("Math.sin(Math.PI/2)").Result;
于 2021-11-08T08:52:54.753 回答