【发布时间】:2013-07-09 12:29:29
【问题描述】:
我有一组Task(很多,大约 400 个):
IEnumerable<Task> tasks = ...
我想同时运行它们,然后等待它们中的每一个。我使用这段代码来运行任务:
Task.Run(async () => { ... });
每个任务都会自己运行异步方法,这就是为什么我需要 lambda 中的 async 关键字。在这些嵌套任务中,众所周知的是发送的HTTP 请求和接收的HTTP 响应。
我尝试了两种不同的方法来等待所有任务完成:
await Task.WhenAll(tasks);
和
foreach (var task in tasks)
{
await task;
}
在我看来,先验的看起来完全一样(但当然它们似乎不一样,否则我一开始就不会在这里发帖......)。
第一种方法使任务运行得更快,但在输出窗口中有大量A first chance exception of type 'System.Net.Sockets.SocketException' occurred in System.dll 和其他类似的方法。此外,在调用await Task.WhenAll() 之后,一些任务仍处于WaitingForActivation 状态。
第二种方式速度较慢,并且它看起来任务没有同时运行(我收到HTTP的响应一个接一个,而等待任务的第一种方式使它们几乎都来了同时)。另外,当我使用foreach 循环等待每个任务并且循环后没有任务具有WaitingForActivation 状态时,我在输出窗口中根本看不到first chance exception。
我了解等待一组任务的“最佳”方法是使用WhenAll()(至少为了可读性),但是为什么这两种方法的行为不同?我该如何克服这个问题?理想情况下,我希望任务能够快速运行并确保一切都结束(我在 lambda 中有一个 try catch finally 块来处理服务器错误,并且我没有忘记 finally 中的 if(httpClient != null) httpClient.Dispose()在有人问之前...)。
欢迎任何提示!
编辑:
好的,我尝试了另一件事。我补充说:
.ContinueWith(x => System.Diagnostics.Debug.WriteLine("#### ENDED = " + index)));
对于每个任务,index 是Task 的编号。
使用foreach 循环时,我得到:
#### ENDED = 0
#### ENDED = 1
#### ENDED = 2
#### ENDED = 3
#### ENDED = 4
...
当使用WhenAll() 时,我得到:
#### ENDED = 1
#### ENDED = 3
#### ENDED = 0
#### ENDED = 4
#### ENDED = 8
...
所以使用foreach 循环使我的所有任务同步运行......这也许可以解释为什么我在输出窗口中没有得到任何First Chance Exception,因为系统根本没有受到算法的压力。
EDIT2:
示例代码:http://pastebin.com/5bMWicD4
它使用这里提供的公共服务:http://timezonedb.com/
【问题讨论】:
-
它没有让它们同步运行(它们已经在运行),但是你同步得到了结果,并且按照你创建它们的顺序
-
await和Task的方式不应影响该任务的执行方式。这真的是您的代码,而不是像foreach (var job in jobs) { await Task.Run(…); }这样的代码吗?您能否发布一个简短但完整的示例代码来演示这一点? -
@svick 我在帖子中添加了一个示例代码 :-)
标签: c# multithreading asynchronous async-await c#-5.0