Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Plataformas suportadas: Win32, Windows Forms, WinUI, WPF.
O controlo WebView2 baseia-se no Modelo de Objeto de Componente (COM) e tem de ser executado num thread single Threaded Apartments (STA).
Acesso thread-safe
O WebView2 tem de ser criado num thread de IU que utilize uma bomba de mensagens. Todas as chamadas de retorno ocorrem nesse thread e os pedidos para o WebView2 têm de ser feitos nesse thread. Não é seguro utilizar o WebView2 a partir de outro thread.
A única exceção é para a Content propriedade de CoreWebView2WebResourceRequest. O Content fluxo de propriedades é lido a partir de um thread de fundo. O fluxo deve ser ágil ou deve ser criado a partir de um STA em segundo plano, para impedir a degradação do desempenho do thread de IU.
As propriedades do objeto são de thread único. Por exemplo, chamar CoreWebView2CookieManager.GetCookiesAsync(null) a partir de um thread que não Main seja com êxito (ou seja, os cookies são devolvidos); no entanto, tentar aceder às propriedades dos cookies (como c.Domain) após essa chamada emitirá uma exceção.
Reentraência
As chamadas de retorno, incluindo processadores de eventos e processadores de conclusão, são executadas em série. Depois de executar um processador de eventos e iniciar um ciclo de mensagens, não é possível executar um processador de eventos ou uma chamada de retorno de conclusão de uma nova entrada. Se uma aplicação WebView2 tentar criar um ciclo de mensagens aninhado ou uma IU modal de forma síncrona num processador de eventos WebView2, esta abordagem leva a uma tentativa de reentraência. Esta reentraência não é suportada no WebView2 e deixaria o processador de eventos na pilha indefinidamente.
Por exemplo, a seguinte abordagem de codificação não é suportada:
private void Btn_Click(object sender, EventArgs e)
{
// Post web message when button is clicked
this.webView2Control.ExecuteScriptAsync("window.chrome.webview.postMessage(\"Open Dialog\");");
}
private void CoreWebView2_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs e)
{
string msg = e.TryGetWebMessageAsString();
if (msg == "Open Dialog")
{
Form1 form = new Form1(); // Create a new form that contains a new WebView2 instance when web message is received.
form.ShowDialog(); // This will cause a reentrancy issue and cause the newly created WebView2 control inside the modal dialog to hang.
}
}
Em vez disso, agende o trabalho adequado a realizar após a conclusão do processador de eventos, conforme mostrado no seguinte código:
private void CoreWebView2_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs e)
{
string msg = e.TryGetWebMessageAsString();
if (msg == "Open Dialog")
{
// Show a modal dialog after the current event handler is completed, to avoid potential reentrancy caused by running a nested message loop in the WebView2 event handler.
System.Threading.SynchronizationContext.Current.Post((_) => {
Form1 form = new Form1();
form.ShowDialog();
form.Closed();
}, null);
}
}
Observação
Para aplicações WinForms e WPF, para obter a pilha de chamadas completa para fins de depuração, tem de ativar a depuração de código nativo para aplicações WebView2, da seguinte forma:
- Abra o seu projeto WebView2 no Visual Studio.
- No Gerenciador de Soluções, clique com o botão direito do rato no projeto WebView2 e, em seguida, selecione Propriedades.
- Selecione o separador Depurar e, em seguida, selecione a caixa de verificação Ativar depuração de código nativo , conforme mostrado abaixo.
Diferimentos
Alguns eventos webView2 leem valores definidos nos argumentos de eventos relacionados ou iniciam alguma ação após a conclusão do processador de eventos. Se também precisar de executar uma operação assíncrona, como um processador de eventos, utilize o GetDeferral método nos argumentos de eventos dos eventos associados. O objeto devolvido Deferral garante que o processador de eventos não é considerado concluído até que o Complete método do Deferral seja pedido.
Por exemplo, pode utilizar o NewWindowRequested evento para fornecer um CoreWebView2 para ligar como uma janela subordinada quando o processador de eventos for concluído. No entanto, se precisar de criar assíncronamente o CoreWebView2, deve chamar o GetDeferral método no NewWindowRequestedEventArgs. Depois de criar assíncronamente e CoreWebView2 definir a NewWindow propriedade no NewWindowRequestedEventArgs, chame Complete no Deferral objeto que é devolvido pelo GetDeferral método .
Diferimentos em C#
Ao utilizar um Deferral em C#, a melhor prática é utilizá-lo com um using bloco. O using bloco garante que o Deferral é concluído mesmo que seja emitida uma exceção no meio do using bloco. Se, em vez disso, tiver código para chamar Completeexplicitamente , mas for emitida uma exceção antes Complete de a chamada ocorrer, o diferimento só será concluído algum tempo depois, quando o recoletor de lixo recolher e eliminar o diferimento. Entretanto, o WebView2 aguarda que o código da aplicação processe o evento.
Por exemplo, não faça o seguinte, porque se existir uma exceção antes de chamar Complete, o WebResourceRequested evento não é considerado "processado" e impede o WebView2 de compor esse conteúdo Web.
private async void WebView2WebResourceRequestedHandler(CoreWebView2 sender,
CoreWebView2WebResourceRequestedEventArgs eventArgs)
{
var deferral = eventArgs.GetDeferral();
args.Response = await CreateResponse(eventArgs);
// Calling Complete is not recommended, because if CreateResponse
// throws an exception, the deferral isn't completed.
deferral.Complete();
}
Em vez disso, utilize um using bloco, como no exemplo seguinte. O using bloco garante que o Deferral está concluído, quer exista ou não uma exceção.
private async void WebView2WebResourceRequestedHandler(CoreWebView2 sender,
CoreWebView2WebResourceRequestedEventArgs eventArgs)
{
// The using block ensures that the deferral is completed, regardless of
// whether there's an exception.
using (eventArgs.GetDeferral())
{
args.Response = await CreateResponse(eventArgs);
}
}
Bloquear o thread da IU
O WebView2 baseia-se na bomba de mensagens do thread da IU para executar chamadas de retorno do processador de eventos e chamadas de retorno de conclusão do método assíncrono. Se utilizar métodos que bloqueiam a bomba de mensagens, como Task.Result ou WaitForSingleObject, os processadores de eventos WebView2 e os processadores de conclusão do método assíncrono não são executados. Por exemplo, o código seguinte não é concluído porque Task.Result para a bomba de mensagens enquanto aguarda pela ExecuteScriptAsync conclusão. Uma vez que a bomba de mensagens está bloqueada, não ExecuteScriptAsync é possível concluir.
Por exemplo, o seguinte código não funciona porque utiliza Task.Result.
private void Button_Click(object sender, EventArgs e)
{
string result = webView2Control.CoreWebView2.ExecuteScriptAsync("'test'").Result;
MessageBox.Show(this, result, "Script Result");
}
Em vez disso, utilize um mecanismo assíncrono await , como async e await, que não bloqueia a bomba de mensagens ou o thread da IU. Por exemplo:
private async void Button_Click(object sender, EventArgs e)
{
string result = await webView2Control.CoreWebView2.ExecuteScriptAsync("'test'");
MessageBox.Show(this, result, "Script Result");
}
Confira também
- Introdução ao WebView2
- Repositório WebView2Samples - um exemplo abrangente de capacidades do WebView2.
- Referência da API webView2