繁体   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