[英]Why is this async method blocking the UI thread?
我正在努力解決這段代碼引發的問題:
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();
}
}
我在這里想要實現的是為XAML的WebView
找到一個解決方法,我發現它非常草率。 我希望能夠在它上面繪制內容,但我不能這樣做我基本上做的是重復拍攝WebView
快照(使用WebViewBrush
)(基於int FPS
字段),然后設置Background
屬性帶有此快照的名為“ webViewContent
”的畫布。 目的是在畫布上顯示動畫,同時仍然可以在其上繪制(如果我不執行這些快速快照,畫布將顯示靜止圖像)。
它現在工作正常(我成功地將任何Tapped
事件重定向到WebView
的內部,以便正確處理按鈕/鏈接/ ...的點擊),但它有點滯后。 慢點是wvb.Redraw()
我想知道如何改善我的線程的性能。 在 Task.Delay
期間看起來UI是響應的,但是否則被阻止...
任何意見/建議都非常歡迎!
編輯:這是我如何計算Redraw
調用(我認為這是導致問題的原因,因為刪除它會使應用程序響應非常快):
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);
}
這在輸出窗口中給出了這些結果:
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
畢竟不是那么多......
在Task.Delay期間看起來UI是響應的,但是否則被阻止...
嗯,是。 這正是發生的事情。 Task.Delay
是你讓UI線程工作的唯一機會。 您的異步方法正在UI線程上執行 - 一旦“延遲”任務完成,您將最終繼續等待在UI線程上執行,該線程將重繪然后再次延遲。
從根本上說,如果您的Redraw
方法太慢而無法每秒調用~60次,則需要采用不同的方法。
理解async
不會將該方法放在不同的線程上非常重要 - 它只允許您異步操作。 (您的描述和標題表明您希望您的方法在任何重要時間都不使用UI線程。)
此外,正如Stephen Cleary所說,使用DispatcherTimer
是在UI線程上定期執行代碼的一種更好的方法。
Task.Delay
對於重復執行許多短暫超時並不是特別有效。 你會產生很多垃圾。
我建議在這種情況下使用調度程序計時器或類似計時器。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.