I am struggling with an issue which is raised by this piece of code:
private int FPS = 60;
void WebView_LoadCompleted(object sender, NavigationEventArgs e)
{
WebviewContentWorker();
}
private async void WebviewContentWorker()
{
WebViewBrush wvb = new WebViewBrush();
wvb.SetSource(WebView);
wvb.Redraw(); //we must redraw at least once before collapsing the WebView
WebView.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
while (true)
{
webViewContent.Background = wvb; //webViewContent is a canvas
await Task.Delay(1000 / FPS);
wvb.Redraw();
}
}
What I'm trying to achieve here is to find a workaround for XAML's WebView
which I find very sloppy. I want to be able to draw things on top of it but I can't so what I'm basically doing is taking snapshots of the WebView
(using the WebViewBrush
) repeatedly (based on the int FPS
field) and then setting the Background
property of the canvas named " webViewContent
" with this snapshot. The aim is to have animations displayed on the canvas while still being able to draw on top of it (if I don't do these fast snapshots, the canvas will display a still image).
It is working fine now (I successfully redirect any Tapped
event to the inside of the WebView
so that clicks on buttons/links/... are properly handled) but it is somehow laggy. The slow bit being wvb.Redraw()
I was wondering how I could improve the performance of my thread. It looks like the UI is responsive during the Task.Delay
but is blocked otherwise...
Any input/advice is very welcome!
Edit: Here is how I timed the Redraw
call (which I believe is what causes the problem since removing it makes the application very responsive):
while (true)
{
webViewContent.Background = wvb;
await Task.Delay(1000 / FPS);
sw.Reset();
sw.Start();
wvb.Redraw();
sw.Stop();
System.Diagnostics.Debug.WriteLine(sw.Elapsed.TotalMilliseconds);
}
Which gives me these results in the output window:
0,094
0,058
0,041
0,053
0,057
0,038
0,032
0,033
0,032
0,038
0,035
0,03
0,042
0,028
0,044
0,031
0,033
0,029
0,034
0,03
0,052
0,029
So not so much after all...
It looks like the UI is responsive during the Task.Delay but is blocked otherwise...
Well yes. That's exactly what's happening. Task.Delay
is the only chance you're giving the UI thread to work. Your asynchronous method is executing on the UI thread - as soon as the "delaying" task completes, you'll end up with a continuation waiting to execute on the UI thread which will redraw and then delay again.
Fundamentally, if your Redraw
method is too slow to be called ~60 times per second, you need a different approach.
It's very important to understand that async
doesn't put the method onto a different thread - it just allows you to act asynchronously. (Your description and title suggest that you expected your method not to be using the UI thread for any significant time.)
Additionally, as Stephen Cleary says, using a DispatcherTimer
is a generally-better way of executing code periodically on the UI thread.
Task.Delay
is not particularly efficient for repeatedly doing many short timeouts. You'll generate a lot of garbage.
I would recommend using a dispatcher timer or similar for this scenario.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.