簡體   English   中英

連續運行多個任務

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM