将 WhenAll 与动态大小列表一起使用
Using WhenAny With Dynamic Sized List
有谁知道如果在等待后将元素添加到 list
,Task.WhenAny(IEnumerable<Task>)
是否会按预期工作?即:
class lunch {
private List<Task> lunchTasks = new List<Task>();
public void MakeLunch() {
Task makeSandwich = new Task();
Task eatSandwich = new Task();
makeSandwich.Delay(-1);
eatSandwich.Delay(-1);
lunchTasks.Add(makeSandwich);
lunchTasks.Add(eatSandwich);
await Task.WhenAny(lunchTasks).ConfigureAwait(false);
}
public void CleanUp() {
Task cleanUp = Task.CompletedTask;
lunchTasks.Add(cleanUp);
}
}
假设 CleanUp()
在 MakeLunch()
之后异步调用,MakeLunch()
会 return/complete 吗?
没有。 WhenAny
and WhenAll
methods are making immediately a defensive copy of the supplied enumerable, as you can see in the source code:
public static Task<Task> WhenAny(IEnumerable<Task> tasks)
{
if (tasks == null) throw new ArgumentNullException("tasks");
Contract.EndContractBlock();
// Make a defensive copy, as the user may manipulate the tasks collection
// after we return but before the WhenAny asynchronously completes.
List<Task> taskList = new List<Task>();
foreach (Task task in tasks)
{
if (task == null) throw new ArgumentException(Environment
.GetResourceString("Task_MultiTaskContinuation_NullTask"), "tasks");
taskList.Add(task);
}
if (taskList.Count == 0)
{
throw new ArgumentException(Environment
.GetResourceString("Task_MultiTaskContinuation_EmptyTaskList"), "tasks");
}
// Previously implemented CommonCWAnyLogic() can handle the rest
return TaskFactory.CommonCWAnyLogic(taskList);
}
所以以后对可枚举的任何修改都将被忽略。
有谁知道如果在等待后将元素添加到 list
,Task.WhenAny(IEnumerable<Task>)
是否会按预期工作?即:
class lunch {
private List<Task> lunchTasks = new List<Task>();
public void MakeLunch() {
Task makeSandwich = new Task();
Task eatSandwich = new Task();
makeSandwich.Delay(-1);
eatSandwich.Delay(-1);
lunchTasks.Add(makeSandwich);
lunchTasks.Add(eatSandwich);
await Task.WhenAny(lunchTasks).ConfigureAwait(false);
}
public void CleanUp() {
Task cleanUp = Task.CompletedTask;
lunchTasks.Add(cleanUp);
}
}
假设 CleanUp()
在 MakeLunch()
之后异步调用,MakeLunch()
会 return/complete 吗?
没有。 WhenAny
and WhenAll
methods are making immediately a defensive copy of the supplied enumerable, as you can see in the source code:
public static Task<Task> WhenAny(IEnumerable<Task> tasks)
{
if (tasks == null) throw new ArgumentNullException("tasks");
Contract.EndContractBlock();
// Make a defensive copy, as the user may manipulate the tasks collection
// after we return but before the WhenAny asynchronously completes.
List<Task> taskList = new List<Task>();
foreach (Task task in tasks)
{
if (task == null) throw new ArgumentException(Environment
.GetResourceString("Task_MultiTaskContinuation_NullTask"), "tasks");
taskList.Add(task);
}
if (taskList.Count == 0)
{
throw new ArgumentException(Environment
.GetResourceString("Task_MultiTaskContinuation_EmptyTaskList"), "tasks");
}
// Previously implemented CommonCWAnyLogic() can handle the rest
return TaskFactory.CommonCWAnyLogic(taskList);
}
所以以后对可枚举的任何修改都将被忽略。