如何同时执行多个异步任务

时间:2017-02-07 20:44:30

标签: c# asynchronous task

我对此代码感到困惑。 根据包含此代码的文档, 它调用允许它们执行的每个任务 同时,然后等待他们两个完成。

我不明白执行顺序是如何运作的。通过声明任务var firstTask = DoSomethingAsync();,这会导致任务开始执行吗?我认为没有await表达式就是同步的。

public async Task RunConcurrentTasks()
{
    var firstTask = DoSomethingAsync();
    var secondTask = DoSomethingElseAsync();

    await firstTask;
    await secondTask;
} 

此外,此代码是否实现了相同的结果?

public async Task RunConcurrentTasks()
{
    var firstTask = DoSomethingAsync();
    var secondTask = DoSomethingElseAsync();

    await Task.WhenAll(firstTask, secondTask);
}

4 个答案:

答案 0 :(得分:6)

  

var firstTask = DoSomethingAsync();这会导致任务开始执行吗?

是。它更好! DoSomethingAsync在其名称中承诺以异步方式执行某些操作,因此,如果它不会将您送回执行任务,那么它的名称就是谎言。

  

执行如何进入下一行以调用第二个任务?

我不明白这个问题。

  

我认为没有等待表达式就是同步的。

你的信念是错误的。 "等待"并不意味着"使这个异步"。等待既不创造也不破坏异步;它只管理现有的异步。 DoSomethingAsync 已经异步独立于任何await。再次,它表示它以异步方式执行某些操作,因此最好能够做到这一点!

您的示例中的

await仅为return。这意味着"返回我的调用者,并在等待任务完成后的某个时间再次开始运行此方法。"它是异步等待

await视为yield return。当您在迭代器块中并且遇到收益率返回时,该方法返回,然后它将在未来的某个时刻从中断处继续。 await基本相同;只是机制略有不同。

另一种思考方式是await标记当前方法无法继续运行直到等待任务完成的点。由于该方法无法继续运行,因此返回。

同样,await对其右侧的呼叫不执行任何操作。它只是一个运营商,它遵守运营商的所有正常规则:

await Foo();

var blah = Foo();
await blah;

是一样的,就像

一样
var x = Foo() + Bar();

var f = Foo(); 
var b = Bar(); 
var x = f + b;

是一回事。 Await不会为其操作数做一些神奇的事情,而不仅仅是+对其操作数做了一些神奇的事情。这只是一种特殊的回报。

  

此外,此代码是否也做同样的事情?

请不要在一个问题中提出两个问题。如果您有两个问题,请发两个问题。

问题不明确。这两个工作流的语义是RunConcurrentTasks返回的任务在其子任务完成时发出信号,如果这是你要求的话。

答案 1 :(得分:1)

  

通过声明任务var firstTask = DoSomethingAsync();这会导致任务开始执行吗?

  

执行如何进入下一行以调用第二个任务?

它将运行DoSomethingAsync,直到它达到其产生的第一个await。此时,DoSomethingAsync返回尚未完成的任务,并且调用者RunConcurrentTasks继续到下一行。

  

我认为没有等待表达式就是同步的。

不,它仍然是异步的。 await无法运行任何内容。 await将导致消费代码异步等待("等待")以使任务完成

您可能会发现我的async intro有帮助。

答案 2 :(得分:0)

在调用异步方法时,使用parenthesys (),例如DoSomethingAsync();将开始执行异步功能。它将立即返回Task,其中包含有关正在执行的异步功能的信息,并让系统知道它何时完成。

要按顺序运行它们,只需等待每一个而不是等待WhenAll调用。就这样:

public async Task RunConcurrentTasks()
{
    await DoSomethingAsync();
    await DoSomethingElseAsync();
}

现在DoSomethingElseAsync会在执行前等待DoSomethingAsync的调用。

答案 3 :(得分:0)

Task Documentation

  

Task类表示一个不返回值且通常执行异步的操作。任务对象是.NET Framework 4中首次引入的基于任务的异步模式的核心组件之一。因为Task对象执行的工作通常在线程池线程上异步执行,而不是在主应用程序线程上同步执行。

这是您的代码注释,希望这更有意义。

public async Task RunConcurrentTasks()
{
    // starts DoSomethingAsync and returns a Task which contains the information about the running state of that operation
    // the thread that called this gets that Task as a result immediatly and can continue on to the next statement while this is running
    var firstTask = DoSomethingAsync();

    // starts DoSomethingElseAsync and returns a Task which contains the information about the running state of that operation
    // the thread that called this gets that Task as a result immediatly and can continue on to the next statement while this is running
    var secondTask = DoSomethingElseAsync();

    // suspend the execution of the method until the awaited task completes
    // only then do we proceed to the next line (assuming no exception was thrown)
    await firstTask;

    // suspend the execution of the method until the awaited task completes
    // only then do we proceed to the next line (assuming no exception was thrown)
    await secondTask;
} 


public async Task RunConcurrentTasks()
{
    // starts DoSomethingAsync and returns a Task which contains the information about the running state of that operation
    // the thread that called this gets that Task as a result immediatly and can continue on to the next statement while this is running
    var firstTask = DoSomethingAsync();

    // starts DoSomethingElseAsync and returns a Task which contains the information about the running state of that operation
    // the thread that called this gets that Task as a result immediatly and can continue on to the next statement while this is running
    var secondTask = DoSomethingElseAsync();

    // suspend the execution of the method until the awaited DoSomethingAsync AND DoSomethingElseAsync have completed
    // only then do we proceed to the next line (assuming no Exceptions was thrown)
    await Task.WhenAll(firstTask, secondTask);
}

来自评论

  

如果我愿意,我如何同步进行?

Await documentation

  

await运算符应用于异步方法中的任务,以暂停方法的执行,直到等待的任务完成为止

每次调用后立即使用await,这可确保执行不会继续执行下一行,直到从等待执行的任务返回结果(或异常)。 它实际上并没有在技术意义上使它同步。因此,请参考第一个示例并重新排序行,以便在开始第一个操作之后和开始之前调用await第二次手术。

var firstTask = DoSomethingAsync();
await firstTask;
var secondTask = DoSomethingElseAsync();
await secondTask;

也可以改写为

await DoSomethingAsync();
await DoSomethingElseAsync();