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 controle WebView2 é baseado no COM (Component Object Model) e deve ser executado em um thread STA (Single Threaded Apartments).
Acesso thread-safe
O WebView2 deve ser criado em um thread de interface do usuário que usa uma bomba de mensagens. Todos os retornos de chamada ocorrem nesse thread e as solicitações no WebView2 devem ser feitas nesse thread. Não é seguro usar o WebView2 de outro thread.
A única exceção é para a Content propriedade de CoreWebView2WebResourceRequest. O Content fluxo de propriedades é lido de um thread em segundo plano. O fluxo deve ser ágil ou deve ser criado a partir de um STA em segundo plano, para evitar a degradação do desempenho do thread da interface do usuário.
As propriedades do objeto são de thread único. Por exemplo, a chamada CoreWebView2CookieManager.GetCookiesAsync(null) de um thread diferente Main terá êxito (ou seja, os cookies são retornados); no entanto, a tentativa de acessar as propriedades dos cookies (como c.Domain) após essa chamada gerará uma exceção.
Reentrância
Retornos de chamada, incluindo manipuladores de eventos e manipuladores de conclusão, são executados em série. Depois de executar um manipulador de eventos e iniciar um loop de mensagens, um manipulador de eventos ou um retorno de chamada de conclusão não pode ser executado de maneira reentrante. Se um aplicativo WebView2 tentar criar um loop de mensagem aninhado ou uma interface do usuário modal de forma síncrona em um manipulador de eventos WebView2, essa abordagem levará a uma tentativa de reentrância. Essa reentrância não tem suporte no WebView2 e deixaria o manipulador de eventos na pilha indefinidamente.
Por exemplo, não há suporte para a seguinte abordagem de codificação:
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 apropriado para ocorrer após a conclusão do manipulador de eventos, conforme mostrado no código a seguir:
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 aplicativos WinForms e WPF, para obter a pilha de chamada completa para fins de depuração, você deve ativar a depuração de código nativo para aplicativos WebView2, da seguinte maneira:
- Abra seu projeto WebView2 no Visual Studio.
- No Gerenciador de Soluções, clique com o botão direito do mouse no projeto WebView2 e selecione Propriedades.
- Selecione a guia Depurar e marque a caixa de seleção Habilitar depuração de código nativo , conforme mostrado abaixo.
Adiamentos
Alguns eventos do WebView2 leem valores definidos nos argumentos de eventos relacionados ou iniciam alguma ação após a conclusão do manipulador de eventos. Se você também precisar executar uma operação assíncrona, como um manipulador de eventos, use o GetDeferral método nos argumentos de evento dos eventos associados. O objeto retornado Deferral garante que o manipulador de eventos não seja considerado concluído até que o Complete método do Deferral seja solicitado.
Por exemplo, você pode usar o NewWindowRequested evento para fornecer uma CoreWebView2 janela para se conectar como filho quando o manipulador de eventos for concluído. Mas se você precisar criar o CoreWebView2, de forma assíncrona, deverá chamar o GetDeferral método no NewWindowRequestedEventArgs. Depois de criar de forma assíncrona a CoreWebView2 e definir a NewWindowRequestedEventArgsNewWindow propriedade na chamada CompleteDeferral , no objeto retornado pelo GetDeferral método.
Adiamentos em C#
Ao usar um Deferral em C#, a prática recomendada é usá-lo com um using bloco. O using bloco garante que o Deferral seja concluído mesmo se uma exceção for lançada no meio do using bloco. Se, em vez disso, você tiver código para chamar Completeexplicitamente, mas uma exceção for lançada antes que sua Complete chamada ocorra, o adiamento não será concluído até algum tempo depois, quando o coletor de lixo eventualmente coletar e descartar o adiamento. Enquanto isso, o WebView2 aguarda o código do aplicativo para manipular o evento.
Por exemplo, não faça o seguinte, pois se houver uma exceção antes de chamar Complete, o evento não será considerado "manipulado" e impede que o WebResourceRequested WebView2 renderize esse conteúdo da 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, use um using bloco, como no exemplo a seguir. O using bloco garante que o Deferral seja concluído, independentemente de haver 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 interface do usuário
O WebView2 depende da bomba de mensagens do thread da interface do usuário para executar retornos de chamada do manipulador de eventos e retornos de chamada de conclusão de método assíncrono. Se você usar métodos que bloqueiam a bomba de mensagens, como Task.Result ou WaitForSingleObject, os manipuladores de eventos do WebView2 e os manipuladores de conclusão do método assíncrono não serão executados. Por exemplo, o código a seguir não é concluído, pois Task.Result interrompe o bombeamento de mensagens enquanto aguarda ExecuteScriptAsync a conclusão. Como a bomba de mensagens está bloqueada, o ExecuteScriptAsync não pode ser concluído.
Por exemplo, o código a seguir não funciona, pois usa 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, use um mecanismo assíncrono await como async e await, que não bloqueia a bomba de mensagens ou o thread da interface do usuário. 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 dos recursos do WebView2.
- Referência da API WebView2