我对异步编程很陌生。我想在等待任何任务之前启动一系列任务(发出http请求)。
List<Guid> identifiers;
//Set identifiers to what they should be
var task = Task.WhenAll(identifiers.Select(id => _serviceConnector.GetAsync(id)));
// Call and await another request
await task;
我的问题是:我的http请求是否会通过Task.WhenAll创建任务来启动?或者他们是否会在等待进一步下来之前开始?谢谢!
答案 0 :(得分:2)
WhenAll
立即(并同步)确定其可枚举参数。因此,所有任务都将在WhenAll
返回时启动。
如果你想到这一点,那就有道理了。 WhenAll
必须知道等待的任务数量,以便知道自己的任务何时完成。此外,它必须链接到每个任务,以便在每个子任务完成时通知它。没有其他时间做这项工作; 必须计算并在返回之前设置通知。
答案 1 :(得分:2)
我的http请求是否会在创建任务时启动 通过Task.WhenAll?或者在等待进一步下降之前它们是否会被启动?
当您将IEnumerable<Task>
传递给Task.WhenAll
时,它会枚举任务序列并将它们全部列入清单以供进一步处理:
if (tasks == null) throw new ArgumentNullException("tasks");
List<Task<TResult>> taskList = new List<Task<TResult>>();
foreach (Task<TResult> task in tasks)
{
if (task == null) throw new ArgumentException("tasks");
taskList.Add(task);
}
这意味着如果您传递LINQ查询,它将被执行:
identifiers.Select(id => _serviceConnector.GetAsync(id))
但这并不意味着Task.WhenAll
启动这些任务。例如。如果您的查询将返回尚未启动的任务,那么这些任务将保持非运行状态。例如。以下查询将创建任务但不会启动它们,因此WhenAll
将等待这些任务
var tasks = Enumerable.Range(1, 10).Select(i => new Task<int>(() => i));
var task = Task.WhenAll(tasks);
在您的情况下,一切都取决于GetAsync(id)
方法。如果它创建并启动任务(如HttpClient
那么做),那么所有任务都将在Task.WhenAll
调用开始时创建并启动。
TL; DR Task.WhenAll
方法的实施细节。如上所述,它抓取所有给定的任务(对于IEnumerable参数,它将所有任务放入列表中)并创建类型为WhenAllPromise<T>
的新任务
private sealed class WhenAllPromise<T> : Task<T[]>, ITaskCompletionAction
正如您所看到的,此任务实现了ITaskCompletionAction
。这是一个内部接口,用于向任务添加完成操作 - 延续任务的轻量级版本(因为它是一个简单的操作)。此接口定义单个方法Invoke(Task)
,应在任务完成执行时调用该方法。 Task
有一个内部方法,允许添加这些轻量级延续:
internal void AddCompletionAction(ITaskCompletionAction action)
现在回到WhenAllPromise<T>
课程。它有两个字段:
private readonly Task<T>[] m_tasks;
private int m_count;
在初始化期间,此类将所有给定任务存储在字段数组中,初始化计数器,并为已完成的任务调用continuation或将其自身添加到任务完成操作:
m_tasks = tasks;
m_count = tasks.Length;
foreach (var task in tasks)
{
if (task.IsCompleted) this.Invoke(task); // short-circuit
else task.AddCompletionAction(this); // simple completion action
}
那就是它。任务不是由WhenAllPromise
课程开始的。它仅使用在任务完成时调用的回调操作。在回调操作中,每次完成某些任务时,它会减少m_count,直到完成所有任务并且我们可以获取结果。