[英]async await blocking ui wp8
據我所知async await關鍵字以這種方式工作:當編譯器遇到await關鍵字時,它會暫停執行異步函數給調用者(在本例中是調度程序),等待等待函數完成后台然后返回到該函數。 我對嗎?
這就是我在做的事情:
async private void Button_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
var p = await query("select* from notes", con);
}
這是被調用的函數
async Task<List<notes>> query(string sqlstring, SQLiteConnection con)
{
var p = con.Query<notes>(sqlstring);
Thread.Sleep(5000);
MessageBox.Show(p[0].Data);
return p;
}
這會阻止UI線程。 為什么發生這種情況不應該在遇到await關鍵字時將控制權轉移回調度程序? 如果是這樣,為什么用戶界面會被卡住?
您對await
理解大多是正確的,它只是不完整。 await
不會立即暫停執行當前方法。 首先,需要將值等待解析為值。 通常,您將擁有一種創建Task
的方法。 該任務將同步創建 ,然后在創建該任務后,當前方法的執行將結束,並且將繼續執行該任務以執行該方法的其余部分。
對於async
方法,第一個await
之前的所有內容都將由調用者同步執行。 當第一個await
(或方法的結束,或方法未捕獲的異常)導致該方法返回實際的Task
。
您的query
方法應該能夠非常快速地創建表示操作完成的Task
,然后返回,以便調用者可以await
該Task
。 但事實並非如此,它花費了超過5秒的時間來創建代表何時完成的任務,以及當它最終將任務交給其調用者Task
已經完成時。
這意味着在query
完成任務創建5秒之后, Button_Tap
無法屈服於其調用者(這是UI的消息循環)。
所有這一切都意味着對於Button_Tap
,異步query
需要是異步的,而不是異步的,因為它使用async
關鍵字,但在調用時方法幾乎立即返回,並且在產生控制后執行其工作的意義上是異步的回到來電者。
至於如何使方法異步,這將取決於。 對於IO,例如查詢數據庫,您真正想要的是讓查詢提供程序本身提供固有的異步支持。 您希望有一個返回可以await
的Task
的查詢方法,而不是同步返回其結果。 如果您沒有其他選擇,那么作為最后的手段,您可以使用Task.Run
在非UI線程中執行查詢,然后await
它。
至於Thread.Sleep
,那也是同步阻塞線程。 您需要在一段時間后異步執行某些操作(如果您確實需要延遲)。 您可以使用Task.Delay
。
async Task<List<notes>> query(string sqlstring, SQLiteConnection con)
{
var p = await con.QueryAsync<notes>(sqlstring);
//Or, if there is no asynchronous query method
//var p = await Task.Run(() => con.Query<notes>(sqlstring));
await Task.Delay(5000);
MessageBox.Show(p[0].Data);
return p;
}
另外,您真的不應該嘗試重復使用這樣的數據庫連接。 對於初學者來說,它們並非旨在同時使用。 實際上它們本身就是為了執行一次操作而設計的。 您應該在需要時立即創建連接,並在執行一個操作后立即清理它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.