[英]Run multiple tasks with continuation
我发现一些奇怪的行为在for循环中运行任务并等待它们。 如下所述,代码的作用是为一定数量的任务启动一个“循环”,每个任务创建一个“ ToDo”项目,每个任务都有一个延续,将每个创建的任务分配给一个人,最后将它们分配给listBox调用以便调用UI线程。 这工作正常,但我没有在listBox中获得预期的数据。 我不希望他们被订购,但我确实希望它们能够配对,例如:
Person_8,Todo 8 Person 5,Todo 5等等...
而且它们应该只出现在listBox中! 但是,相反,我得到了奇怪的输出(每次运行的输出都不相同),下面是一些运行代码的示例:
这是代码:
private async void buttonCreateToDo_Click(object sender, EventArgs e){
await CreateToDoAsync();
}
private async Task CreateToDoAsync(){
List<Task> taskList = new List<Task>();
for (int i = 1; i < 10; i++){
var task = Task.Run(() => CreateToDo(i));
Task continuation = task.ContinueWith((antecedent) => Invoke(new AssignTaskDelegate(AssignTask), (new Person() {
Name = $"Person_{i}",
ToDoForPerson = antecedent.Result
})));
taskList.Add(task);
}
await Task.WhenAll(taskList.ToArray());
}
private ToDo CreateToDo(int toDoId) {
return new ToDo(){
Id = toDoId,
Description = $"Todo {toDoId}"
};
}
private void AssignTask(Person person){
listBoxToDo.Items.Add($"{person.Name}, {person.ToDoForPerson.Description}");
}
您的问题是for
循环的运行要比任务的创建快得多,因此到任务运行变量i
已经到达了循环的结尾。
要解决此问题,您需要在循环内复制i
并使用它。
试试这个代码:
private async Task CreateToDoAsync()
{
List<Task> taskList = new List<Task>();
for (int i = 1; i < 10; i++)
{
var local_i = i;
var task = Task.Run(() => CreateToDo(local_i));
Task continuation = task.ContinueWith((antecedent) => Invoke(new AssignTaskDelegate(AssignTask), (new Person()
{
Name = $"Person_{local_i}",
ToDoForPerson = antecedent.Result
})));
taskList.Add(task);
}
await Task.WhenAll(taskList.ToArray());
}
现在,我将优先使用Microsoft的Reactive Framework(NuGet“ System.Reactive”)来完成这项工作。 您的代码如下所示:
private async Task CreateToDoAsync()
{
var query =
from i in Observable.Range(1, 9)
from t in Observable.Start(() => CreateToDo(i))
select new Person() { Name = $"Person_{i}", ToDoForPerson = t };
await query.ObserveOn(listBoxToDo).Do(x => AssignTask(x));
}
做完了 而已。
当我运行代码(将AssignTask
输出到控制台)时,我得到以下信息:
Person_1, Todo 1 Person_2, Todo 2 Person_3, Todo 3 Person_6, Todo 6 Person_7, Todo 7 Person_4, Todo 4 Person_5, Todo 5 Person_8, Todo 8 Person_9, Todo 9
.ObserveOn(listBoxToDo)
适用于Windows窗体,以编组回UI线程。
您正在任务内部的循环中使用变量“ i”。 您的任务开始时“ i”可能已更改。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.