异步等待阻塞ui wp8

时间:2014-08-13 20:25:21

标签: c# multithreading windows-phone-8 asynchronous

据我所知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关键字时将控制权转移回调度程序?如果是这样,为什么UI会被卡住?

1 个答案:

答案 0 :(得分:13)

您对await的理解主要是正确,它只是不完整。 await不会立即暂停执行当前方法。首先,需要将值等待解析为值。通常,您会使用某种方法创建Task该任务将同步创建,然后在创建该任务后,当前方法的执行将结束,并且将继续执行该任务以执行该方法的其余部分。

对于async方法,调用者将同步执行第一个await之前的所有内容。当第一个await(或方法的结尾,或方法未捕获的异常)导致该方法返回实际的Task时。

您的query方法能够非常快速地创建表示操作完成的Task,然后返回,以便调用方可以{{1}那await。但事实并非如此,它会花费超过5秒的时间来创建代表何时完成的任务,以及何时最终将该任务交给其Task已完成的调用者。

这意味着Task无法屈服于调用者(这是UI的消息循环),直到Button_Tap完成其5秒的任务创建。< / p>

所有这一切都意味着query要异步Button_Tap需要异步,而不是异步,因为它使用query关键字,但在方法意义上是异步的在被调用时几乎立即返回,并且在将控制权交还给调用者之后执行其工作。

至于如何使方法异步,这将取决于。对于IO,例如查询数据库,您真正想要的是让查询提供程序本身提供固有的异步支持。您希望拥有一个可以async返回Task的查询方法,而不是同步返回其结果。如果您没有其他选择,那么作为最后的手段,您可以使用await在非UI线程中执行查询,然后使用Task.Run。{/ p>

对于await,它也同步阻塞线程。您需要在一段时间后异步执行某些操作(如果您确实需要延迟)。您可以使用Thread.Sleep

Task.Delay

另一方面,您真的不应该尝试重新使用这样的数据库连接。对于初学者来说,它们并非旨在同时使用。实际上它们本身就是为了执行一次操作而设计的。您应该在需要时立即创建连接,并在执行一个操作后立即清理它。