2016-12-02 262 views
0

只是想确保我得到这个正确的,因为我看到一些奇怪的行为根据我的结果。C# - 等待和异步

public async Task<System.Net.HttpStatusCode> GetJson(Stream inputJson) 
{ 
    ...... 
    ..... 
    ... 
    var query1 = from xxx in new xxx() 
       where xxx.id == myID 
       select xxx; 
    var results1 = await query1.FindAsync(); 

    var query2 = from yyy in new yyy() 
       where yyy.id == myID 
       select yyy; 
    var results2 = await query2.FindAsync(); 
    ... 
    .... 
    ..... 
    return System.Net.HttpStatusCode.OK; 
} 

query2执行后,才query1执行完毕:

如下我定义了一个异步方法?还是并行?

+2

'query2'将在'query1'产生结果后执行。 – ThePerplexedOne

+0

@Polis:一个好的心理捷径是:'await'意思是“异步等待”,所以它*等待。它只是等待而不是阻塞。 –

回答

2

等待后的代码被构造为所谓的延续。关键的部分是这一行:

var results1 = await query1.FindAsync(); 

FindAsync构造一个Task然后await表明,剩下的应该是工作的延续。

这意味着该方法的其余部分将是另一个Task,并且该任务只会在第一个完成后执行。更重要的是,如果第一个任务引发异常,那么第二个任务甚至不会启动。

因此,您的问题的答案是:是的,query2将始终在query1完成后执行。

+0

谢谢。出于好奇,如果一个异步方法中的大部分代码都标记为await,是不是击败了异步方面?我的意思是你可能会同步运行一切,对吧?顺便说一下,我暗示了一个非UI相关的过程。 – Polis

+1

尝试从CPU的角度来看待这一点。不完全受CPU约束的操作(如数据库或网络操作)将返回对其执行的线程的控制权。这将让任务管理器在同一个线程上运行其他任务,从而提高总体CPU利用率。同时做所有这些操作会降低CPU利用率,因为当前线程将被阻塞,并且必须为其他任务启动另一个线程。 –

0

在你的情况下,query1将启动,该方法将暂停执行,直到query1完成。然后才开始query2。如果你想并行执行它们看看Task.WhenAll(...)MSDN

0

是的query2将在await query1.FindAsync()将会执行后返回结果。但要小心它会继续的线程。这取决于。

如果你想同时做到这一点,你可以使用Task.WhenAll方法。 举例:约WhenAll方法()你可以找到here MSDN上

var firstTask = FirstMethodAsync(); 
var secondTask = SecondMethodAsync(); 
await Task.WhenAll(firstTask, secondTask); 
// Here you can pull out Results from firstTask and secondTask. 
var firstResult = firstTask.Result; 
var secondResult = secondTask.Result; 

更多信息。