2014-03-26 457 views
2

我偶然发现了异步等待的奇怪行为。异步等待的异步行为

示例代码:

public class foo 
{ 
    public async static Task<myobj> method1() 
    { 
     var result = await method2(); 

     return result; 
    } 

    private async static Task<myobj> method2() 
    { 
     // omitted for brevity. 
    } 
} 

public class bar 
{ 
    public void caller() 
    { 
     var result = foo.method1().Result; 

     pass(result); 
    } 
} 

这冻结UI。解决方案是在caller()上实现异步等待。

但是这个怎么样:

public class foo 
{ 
    public static myobj method1() 
    { 
     var result = method2().Result; 

     return result; 
    } 

    private async static Task<myobj> method2() 
    { 
     // omitted for brevity. 
    } 
} 

public class bar 
{ 
    public void caller() 
    { 
     var result = foo.method1(); 

     pass(result); 
    } 
} 

这种自由的工作。

私人电话与其他类别的上行方法有什么不同?

+2

确切的情况在这里描述:http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html – Noseratio

回答

4

正如我在评论中提到的,第一种情况是described in great details by Stephen Cleary in his blog

该死锁发生在await method2()await延续通过SynchronizationContext.Post发布到UI线程的同步上下文。但是UI线程已经被阻塞在这条线上:foo.method1().Result。消息泵被阻塞,并且继续回调从不被泵送和调用,造成死锁。

在第二种情况下,我没有在任何地方看到await。也就是说,你所显示的代码不会有任何异步。我想这就是它工作的原因。