win8 await关键字后遗症

对于异步方法调用“GetAwaiter()”或者“Wait()”方法都将导致“等待调用方完成执行”;
异步方法中使用await关键字会导致await关键字之后代码都进行默认的线程封送,这种封送是默认封送。在metro应用中,默认封送的目标对象是UI线程。
所以,等你在UI线程上调用Wait()或者GetAwaiter()其结果就是“等待UI线程执行完成”。在线程中等待自身结束,这个结果不用说就是死锁。
 
如果想要在UI线程上等待异步方法的完成,那么必须保证异步方法的await封送不会封送到默认的UI线程上,
Task<TResult>对象有一个ConfigureAwait方法,参数是一个boolean类型,当参数为false的时候意为取消默认封送,改为自动封送。
在metro应用中,最好是所有使用await的地方都不要使用默认封送模式,这样一方面UI线程上的跳跃点会减少很多(UI线程的状态机压力很减小),另一方面,UI线程的空闲率会提高,当然还有可解决其上碰到的问题。
 
看一下如下代码:
方法private void Button_Click_1是一个button的单机事件方法:
方法geturlstring是一个自定义的方法:
当用户单击激发Button_Click_1方法后,UI线程不会出现卡顿
但如果将红色区域的代码去掉,当单击事件激发之后,会导致UI卡顿,这是因为没有红色代码之后,那个庞大的循环是在UI线程上执行的。而如果有红色代码(之前说过的会自动封送),庞大的循环是不在UI上执行的,所以不会卡顿
    async    private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            //var o = geturlstring().GetAwaiter().GetResult();
            this.text.Text = await geturlstring();
             //string html = await geturlstring().ConfigureAwait(false);
             //this.text.Text = html;
            //var o = geturlstring();
            //o.Wait();
            //this.text.Text = o.Result;
        }        
async private static Task<string> geturlstring()
        {
            string html = "" ;
            System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
            html = await client.GetStringAsync("http://www.baidu.com").ConfigureAwait(false);
            for (int i = 0; i < 1000000000; i++)
            {
                ;
            }
            return html;
        }
posted @ 2012-07-04 10:53  think_do  阅读(575)  评论(0编辑  收藏  举报