2

注意:这基本上只是说明我对async. 也许它可以帮助其他困惑的人。

我在一个循环中做一些HttpClient async await请求,我注意到这些请求似乎是按顺序完成的(它在开始下一次迭代之前等待结果)。

所以我尝试使用await Task.Delay循环而不是网络请求进行测试。

也许我已经失去了情节,但我会认为await在一个循环中可能会导致循环的下一次迭代在等待结果时开始。相反,似乎一切都是按顺序执行的:

int _iterations = 1000;
int _count= 0;
Stopwatch _stopwatch = new Stopwatch();
_stopwatch.Start();                      

for (int i = 0; i < _iterations; i++)
{
    Console.WriteLine("Elapsed: {0}. Calls count: {1}.", _stopwatch.Elapsed, ++_count);
    await Task.Delay(5000);
    Console.WriteLine("Calls count again: {0}", _count);
}

这导致:

Elapsed: 00:00:00.0000059. Calls count: 1.
Calls count again: 1
Elapsed: 00:00:05.0022733. Calls count: 2.
Calls count again: 2
Elapsed: 00:00:10.0100470. Calls count: 3.
Calls count again: 3
Elapsed: 00:00:15.0182479. Calls count: 4.

是的,我可以省略await并将返回Task的 s 添加到某个数组并使用Task.WhenAll. 但令我惊讶的await是,它在我的循环中被阻塞,并且它都是按顺序执行的。这是正常的吗?

编辑:所以总而言之:我在那里有点困惑。控制返回到循环外部await。这是有道理的,因为它模仿了同步类比,但当然不会阻塞线程。

4

3 回答 3

3

这就是重点await:代码的外观和行为与普通同步代码几乎相同,只是它没有阻塞线程。如果您想同时开始许多作业,然后等待它们全部完成,则必须移动awaitafter 循环。

类似于(假设带下划线的标识符是字段):

async Task PerformIteration()
{
    Console.WriteLine(
        "Elapsed: {0}. Calls count: {1}.", _stopwatch.Elapsed, ++_count);

    await Task.Delay(5000);

    Console.WriteLine("Calls count again: {0}", _count);
}

...

var tasks = new List<Task>();

for (int i=0; i<_iterations; i++)
{
    tasks.Add(PerformIteration());
}

await Task.WhenAll(tasks);

如果您想在每次迭代完成后立即执行某些操作(在您的情况下为第二个WriteLine()),则需要使用单独的方法。如果您不需要,您可以直接将结果添加Task.Delay()到 s 的集合中Task

于 2013-09-30T11:06:00.963 回答
3

这是预期的行为。但是,当您说呼叫阻塞时,您就错了。UI线程在使用时不会被阻塞await——它实际上是fork-and-continue的一种变体。当执行命中await时,您立即返回到调用者并在等待的调用完成后继续。

因此,从某种意义上说,您确实在等待,但您是异步执行的,因此得名。

如果您想并行执行操作,请使用Task.WhenAllTask.WhenAny构造,然后您可以等待。例子:

await Task.WhenAll(await DownloadAsync(), await DownloadAsync(), await DownloadAsync());
于 2013-09-30T08:45:02.067 回答
2

实际上,await Task.Delay(5000)不会阻塞在您的循环Task.Delay(5000).Wait()中。循环将通过编译器生成的await继续回调在 5 秒内恢复,而最初调用此代码的方法可能会在您进入await此处后立即恢复执行。不久前我回答了一个类似的问题,您可能会发现它很有帮助。它显示了如何在没有await.

于 2013-09-30T08:49:38.600 回答