问题
I'm trying to get some content on a website which is rendered by JavaScript. So I'm running a WebView
with Visibility=Collapsed
. I want to wait unitl NavigationCompleted
and run some JavaScript then return the value.
The code look like:
private async void Foo()
{
// Want to get value here
var content = await GetContent();
}
private async Task<string> GetContent()
{
string content;
async void handler(WebView sender, WebViewNavigationCompletedEventArgs args)
{
content = await webView.InvokeScriptAsync("eval", new string[] { script });
webView.NavigationCompleted -= handler;
}
webView.NavigationCompleted += handler;
webView.Navigate(uri);
return content;
}
Since there is no await in GetContent()
, the function always returns before NavigationCompleted
fired.
回答1:
You could use a SemaphoreSlim
to asynchronously wait for the NavigationCompleted
to get raised and handled:
private async Task<string> GetContent()
{
string content;
using (SemaphoreSlim semaphoreSlim = new SemaphoreSlim(0, 1))
{
async void handler(WebView sender, WebViewNavigationCompletedEventArgs args)
{
content = await webView.InvokeScriptAsync("eval", new string[] { script });
webView.NavigationCompleted -= handler;
semaphoreSlim.Release();
}
webView.NavigationCompleted += handler;
webView.Navigate(uri);
await semaphoreSlim.WaitAsync().ConfigureAwait(false);
}
return content;
}
回答2:
I think you should use TaskCompletionSource. Create a source, and set its result at the end of the event handler, after you execute the script. Before you return the content, await the task of the task completion source.
回答3:
If you want to wait for something, you can use ManualResetEvent
. Just ensure that you don't use ManualResetEvent.WaitOne
on the UI thread as it would hang the app.
来源:https://stackoverflow.com/questions/55086961/uwp-webview-await-navigate