[英]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.